Przeglądaj źródła

Merge branch 'master' of http://git.ds-bay.com/project/kmall-pt-general

xwh 4 lat temu
rodzic
commit
f47330df4e

+ 23 - 0
kmall-admin/pom.xml

@@ -50,6 +50,29 @@
             <scope>provided</scope>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+            <version>3.15</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>3.15</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml-schemas</artifactId>
+            <version>3.15</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>stax-api</artifactId>
+                    <groupId>stax</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+
     </dependencies>
 
     <build>

+ 231 - 0
kmall-admin/src/main/java/com/kmall/admin/controller/statistics/MonthlyCustomersController.java

@@ -2,6 +2,8 @@ package com.kmall.admin.controller.statistics;
 
 import com.kmall.admin.dao.GoodsDao;
 import com.kmall.admin.dao.ProductStoreRelaDao;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 import com.kmall.admin.dao.statistics.MonthlyCustomersDao;
 import com.kmall.admin.dao.statistics.WechatFollowersDao;
 import com.kmall.admin.entity.GoodsEntity;
@@ -15,16 +17,26 @@ import com.kmall.admin.utils.ShiroUtils;
 import com.kmall.common.utils.R;
 import com.kmall.common.utils.excel.ExcelExport;
 import com.kmall.common.utils.excel.ExcelUtil;
+import org.apache.commons.lang.StringUtils;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.apache.shiro.SecurityUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
+import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.io.*;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.net.URLEncoder;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.*;
@@ -660,4 +672,223 @@ public class MonthlyCustomersController {
 
 
 
+
+    @RequestMapping("/exportSelectedMonthData")
+    public void exportSelectedMonthData(@RequestParam("startMonth") String startMonth, @RequestParam("endMonth") String endMonth
+    ,@RequestParam("monthNumber") Integer monthNumber
+    ,HttpServletRequest request ,HttpServletResponse response) {
+        List<String> dateList = new ArrayList<>();
+        Map<String, Object> returnMap = new HashMap<>();
+        try {
+            calculateDifferentMonth(dateList, startMonth, endMonth);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        try {
+            String merchSn = null;
+            SysUserEntity sysUser = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
+            if(!"1".equals(sysUser.getRoleType())){
+                merchSn = sysUser.getMerchSn();
+            }
+            List<MonthlySalesGrowthEntity> monthlySalesGrowthEntityList = monthlyCustomersService.exportSelectedMonthData(startMonth,endMonth,merchSn,dateList.size(),monthNumber);
+            ExcelExport ee = new ExcelExport("Wechat Followers Growth");
+            String[] header = new String[]{"序号","sku","产品名称","月份","销售数","平均销售","总库存","店铺库存","园区库存","在途库存","月均预订量","月消耗预订量","统计月份","预定月份","预定数"};
+            List<Map<String, Object>> list = new ArrayList<>();
+            int count = 1;
+            if (monthlySalesGrowthEntityList!=null && monthlySalesGrowthEntityList.size()>0) {
+                for (MonthlySalesGrowthEntity monthlySalesGrowthEntity : monthlySalesGrowthEntityList) {
+                    LinkedHashMap<String, Object> map = new LinkedHashMap<>();
+                    map.put("序号",count++ +"");
+                    map.put("sku",monthlySalesGrowthEntity.getSku());
+                    map.put("产品名称",monthlySalesGrowthEntity.getGoodsName());
+                    map.put("月份",monthlySalesGrowthEntity.getSalesMonth());
+                    map.put("销售数",monthlySalesGrowthEntity.getTotalNumber());
+                    map.put("平均销售",monthlySalesGrowthEntity.getAvgSalesNumber());
+                    map.put("总库存",monthlySalesGrowthEntity.getTotalCount());
+                    map.put("店铺库存",monthlySalesGrowthEntity.getStockNumber());
+                    map.put("在途库存",monthlySalesGrowthEntity.getNumber());
+                    map.put("园区库存",monthlySalesGrowthEntity.getGoodsNumber());
+                    map.put("月均预订量",new BigDecimal(monthlySalesGrowthEntity.getAvgSalesNumber()).multiply(
+                            new BigDecimal(monthNumber)).setScale(2,BigDecimal.ROUND_HALF_UP).toString() );
+                    // 总库存 -  M*单品每月平均销量
+                    map.put("月消耗预订量",new BigDecimal(monthlySalesGrowthEntity.getTotalCount()).subtract(
+                            new BigDecimal(dateList.size()).multiply(new BigDecimal(monthlySalesGrowthEntity.getAvgSalesNumber())).setScale(2,RoundingMode.HALF_UP)).toString());
+                    map.put("统计月份",dateList.size()+"");
+                    map.put("预定月份",monthNumber+"");
+                    map.put("预定数",monthlySalesGrowthEntity.getPredeterminedNumber());
+                    list.add(map);
+                }
+            }
+            Map<String, List<Map<String, Object>>/*该list为每个sheet页的数据*/> map = Maps.newHashMap();
+            map.put("测试合并数据", list);
+            createExcel(header, map, new int[]{0,1,2},request,response);
+//            ee.addSheetByMap("Wechat Followers Growth", list, header);
+//            ee.export(response);
+//            return R.ok();
+        } catch (Exception e) {
+            e.printStackTrace();
+//            return R.error(e.getMessage());
+        }
+    }
+
+
+    public String createExcel(String[] title, Map<String, List<Map<String, Object>>> maps, int[] mergeIndex
+            ,HttpServletRequest request ,HttpServletResponse response){
+        if (title.length==0){
+            return null;
+        }
+        /*初始化excel模板*/
+        Workbook workbook = new XSSFWorkbook();
+        Sheet sheet = null;
+        int n = 0;
+        /*循环sheet页*/
+        for(Map.Entry<String, List<Map<String/*对应title的值*/, Object>>> entry : maps.entrySet()){
+            /*实例化sheet对象并且设置sheet名称,book对象*/
+            try {
+                sheet = workbook.createSheet();
+                workbook.setSheetName(n, entry.getKey());
+                workbook.setSelectedTab(0);
+            }catch (Exception e){
+                e.printStackTrace();
+            }
+            /*初始化head,填值标题行(第一行)*/
+            Row row0 = sheet.createRow(0);
+            for(int i = 0; i<title.length; i++){
+                /*创建单元格,指定类型*/
+                Cell cell_1 = row0.createCell(i, Cell.CELL_TYPE_STRING);
+                cell_1.setCellValue(title[i]);
+            }
+            /*得到当前sheet下的数据集合*/
+            List<Map<String/*对应title的值*/, Object>> list = entry.getValue();
+            /*遍历该数据集合*/
+            List<PoiModel> poiModels = Lists.newArrayList();
+            if(null!=workbook){
+                Iterator iterator = list.iterator();
+                int index = 1;/*这里1是从excel的第二行开始,第一行已经塞入标题了*/
+                while (iterator.hasNext()){
+                    Row row = sheet.createRow(index);
+                    /*取得当前这行的map,该map中以key,value的形式存着这一行值*/
+                    Map<String, String> map = (Map<String, String>)iterator.next();
+                    /*循环列数,给当前行塞值*/
+                    for(int i = 0; i<title.length; i++){
+                        String old = "";
+                        /*old存的是上一行统一位置的单元的值,第一行是最上一行了,所以从第二行开始记*/
+                        if(index > 1){
+                            old = poiModels.get(i)==null?"":poiModels.get(i).getContent();
+                        }
+                        /*循环需要合并的列*/
+                        for(int j = 0; j < mergeIndex.length; j++){
+                            if(index == 1){
+                                /*记录第一行的开始行和开始列*/
+                                PoiModel poiModel = new PoiModel();
+                                poiModel.setOldContent(map.get(title[i]));
+                                poiModel.setContent(map.get(title[i]));
+                                poiModel.setRowIndex(1);
+                                poiModel.setCellIndex(i);
+                                poiModels.add(poiModel);
+                                break;
+                            }else if(i > 0 && mergeIndex[j] == i){/*这边i>0也是因为第一列已经是最前一列了,只能从第二列开始*/
+                                /*当前同一列的内容与上一行同一列不同时,把那以上的合并, 或者在当前元素一样的情况下,前一列的元素并不一样,这种情况也合并*/
+                                /*如果不需要考虑当前行与上一行内容相同,但是它们的前一列内容不一样则不合并的情况,把下面条件中||poiModels.get(i).getContent().equals(map.get(title[i])) && !poiModels.get(i - 1).getOldContent().equals(map.get(title[i-1]))去掉就行*/
+                                if(!poiModels.get(i).getContent().equals(map.get(title[i])) || poiModels.get(i).getContent().equals(map.get(title[i])) && !poiModels.get(i - 1).getOldContent().equals(map.get(title[i-1]))){
+                                    /*当前行的当前列与上一行的当前列的内容不一致时,则把当前行以上的合并*/
+                                    CellRangeAddress cra=new CellRangeAddress(poiModels.get(i).getRowIndex()/*从第二行开始*/, index - 1/*到第几行*/
+                                            , poiModels.get(i).getCellIndex()/*从某一列开始*/, poiModels.get(i).getCellIndex()/*到第几列*/);
+                                    if (cra.getNumberOfCells() >= 2) {
+                                        //在sheet里增加合并单元格
+                                        sheet.addMergedRegion(cra);
+                                    }
+                                    //在sheet里增加合并单元格
+                                    /*重新记录该列的内容为当前内容,行标记改为当前行标记,列标记则为当前列*/
+                                    poiModels.get(i).setContent(map.get(title[i]));
+                                    poiModels.get(i).setRowIndex(index);
+                                    poiModels.get(i).setCellIndex(i);
+                                }
+                            }
+                            /*处理第一列的情况*/
+                            if(mergeIndex[j] == i && i == 0 && !poiModels.get(i).getContent().equals(map.get(title[i]))){
+                                /*当前行的当前列与上一行的当前列的内容不一致时,则把当前行以上的合并*/
+                                CellRangeAddress cra=new CellRangeAddress(poiModels.get(i).getRowIndex()/*从第二行开始*/, index - 1/*到第几行*/, poiModels.get(i).getCellIndex()/*从某一列开始*/, poiModels.get(i).getCellIndex()/*到第几列*/);
+                                if (cra.getNumberOfCells() >= 2) {
+                                    //在sheet里增加合并单元格
+                                    sheet.addMergedRegion(cra);
+                                }
+                                /*重新记录该列的内容为当前内容,行标记改为当前行标记*/
+                                poiModels.get(i).setContent(map.get(title[i]));
+                                poiModels.get(i).setRowIndex(index);
+                                poiModels.get(i).setCellIndex(i);
+                            }
+
+                            /*最后一行没有后续的行与之比较,所有当到最后一行时则直接合并对应列的相同内容*/
+                            if(mergeIndex[j] == i && index == list.size()){
+                                CellRangeAddress cra=new CellRangeAddress(poiModels.get(i).getRowIndex()/*从第二行开始*/, index/*到第几行*/, poiModels.get(i).getCellIndex()/*从某一列开始*/, poiModels.get(i).getCellIndex()/*到第几列*/);
+                                //在sheet里增加合并单元格
+                                if (cra.getNumberOfCells() >= 2) {
+                                    //在sheet里增加合并单元格
+                                    sheet.addMergedRegion(cra);
+                                }
+                            }
+                        }
+                        Cell cell = row.createCell(i, Cell.CELL_TYPE_STRING);
+                        cell.setCellValue(map.get(title[i]));
+                        /*在每一个单元格处理完成后,把这个单元格内容设置为old内容*/
+                        poiModels.get(i).setOldContent(old);
+                    }
+                    index++;
+                }
+            }
+            n++;
+        }
+        /*生成临时文件*/
+        String fileName = String.valueOf(new Date().getTime()/1000);
+        try {
+            ByteArrayOutputStream os = new ByteArrayOutputStream();
+            workbook.write(os);
+            byte[] content = os.toByteArray();
+            InputStream is = new ByteArrayInputStream(content);
+            //根据浏览器不同,对文件的名字进行不同的编码设置
+            final String userAgent = request.getHeader("USER-AGENT");
+            String finalFileName = null;
+            if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {    //IE浏览器
+                finalFileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8");
+            } else if (StringUtils.contains(userAgent, "Mozilla")) {   //google,火狐浏览器
+                finalFileName = new String((fileName + ".xlsx").getBytes("UTF-8"), "ISO-8859-1");
+            } else {
+                finalFileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8");   //其他浏览器
+            }
+            // 设置response参数,可以打开下载页面
+            response.reset();
+            response.setContentType("application/vnd.ms-excel;charset=utf-8");
+            response.setHeader("Content-Disposition", "attachment;filename=" + finalFileName);
+            ServletOutputStream out = response.getOutputStream();
+            BufferedInputStream bis = null;
+            BufferedOutputStream bos = null;
+
+            try {
+                bis = new BufferedInputStream(is);
+                bos = new BufferedOutputStream(out);
+                byte[] buff = new byte[2048];
+                int bytesRead;
+                while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
+                    bos.write(buff, 0, bytesRead);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                if (bis != null) {
+                    bis.close();
+                }
+                if (bos != null) {
+                    bos.close();
+                }
+            }
+            os.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return "导出成功";
+    }
+
+
+
 }

+ 44 - 0
kmall-admin/src/main/java/com/kmall/admin/controller/statistics/PoiModel.java

@@ -0,0 +1,44 @@
+package com.kmall.admin.controller.statistics;
+
+public class PoiModel {
+
+    private String content;
+
+    private String oldContent;
+
+    private int rowIndex;
+
+    private int cellIndex;
+
+    public String getOldContent() {
+        return oldContent;
+    }
+
+    public void setOldContent(String oldContent) {
+        this.oldContent = oldContent;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public int getRowIndex() {
+        return rowIndex;
+    }
+
+    public void setRowIndex(int rowIndex) {
+        this.rowIndex = rowIndex;
+    }
+
+    public int getCellIndex() {
+        return cellIndex;
+    }
+
+    public void setCellIndex(int cellIndex) {
+        this.cellIndex = cellIndex;
+    }
+}

+ 5 - 1
kmall-admin/src/main/java/com/kmall/admin/dao/statistics/MonthlyCustomersDao.java

@@ -4,7 +4,6 @@ import com.kmall.admin.entity.MonthlySalesGrowthEntity;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
-import java.util.Map;
 
 /**
  * @author zhangchuangbiao
@@ -26,4 +25,9 @@ public interface MonthlyCustomersDao {
     List<MonthlySalesGrowthEntity> salesByCategory(@Param("startDate") String startDate, @Param("endDate") String endDate, @Param("merchSn") String merchSn);
 
     List<MonthlySalesGrowthEntity> monthlyCategory(@Param("startMonth") String startMonth, @Param("endMonth") String endMonth, @Param("merchSn") String merchSn);
+
+    List<MonthlySalesGrowthEntity> queryAvgSales(@Param("startMonth") String startMonth, @Param("endMonth") String endMonth,
+                                                 @Param("merchSn") String merchSn,
+                                                 @Param("size") int size, @Param("monthNumber") Integer monthNumber);
+
 }

+ 85 - 0
kmall-admin/src/main/java/com/kmall/admin/entity/MonthlySalesGrowthEntity.java

@@ -34,6 +34,19 @@ public class MonthlySalesGrowthEntity implements Serializable {
     private String supplier; // 供应商
     private String cgname; // 品牌名
 
+    private String sku ; // sku
+    private String avgSalesNumber; // 平均销量
+    private String salesMonth; // 销售月份
+    private String stockNumber; // 门店库存
+    private String goodsNumber; // 园区库存
+    private String number; // 在途库存
+    private String totalCount; // 总库存
+    private String predeterminedNumber ; // 预定数量
+    private String predeterminedBoxNumber; // 预定箱数
+    private String avgPredeterminedNumber; // 平均订货量
+    private String avgConsumeNumber; // 平均消耗量
+
+
 
     public String getMerchSn() {
         return merchSn;
@@ -131,4 +144,76 @@ public class MonthlySalesGrowthEntity implements Serializable {
     public void setCgname(String cgname) {
         this.cgname = cgname;
     }
+
+    public String getSku() {
+        return sku;
+    }
+
+    public void setSku(String sku) {
+        this.sku = sku;
+    }
+
+    public String getAvgSalesNumber() {
+        return avgSalesNumber;
+    }
+
+    public void setAvgSalesNumber(String avgSalesNumber) {
+        this.avgSalesNumber = avgSalesNumber;
+    }
+
+    public String getSalesMonth() {
+        return salesMonth;
+    }
+
+    public void setSalesMonth(String salesMonth) {
+        this.salesMonth = salesMonth;
+    }
+
+    public String getStockNumber() {
+        return stockNumber;
+    }
+
+    public void setStockNumber(String stockNumber) {
+        this.stockNumber = stockNumber;
+    }
+
+    public String getGoodsNumber() {
+        return goodsNumber;
+    }
+
+    public void setGoodsNumber(String goodsNumber) {
+        this.goodsNumber = goodsNumber;
+    }
+
+    public String getNumber() {
+        return number;
+    }
+
+    public void setNumber(String number) {
+        this.number = number;
+    }
+
+    public String getTotalCount() {
+        return totalCount;
+    }
+
+    public void setTotalCount(String totalCount) {
+        this.totalCount = totalCount;
+    }
+
+    public String getPredeterminedNumber() {
+        return predeterminedNumber;
+    }
+
+    public void setPredeterminedNumber(String predeterminedNumber) {
+        this.predeterminedNumber = predeterminedNumber;
+    }
+
+    public String getPredeterminedBoxNumber() {
+        return predeterminedBoxNumber;
+    }
+
+    public void setPredeterminedBoxNumber(String predeterminedBoxNumber) {
+        this.predeterminedBoxNumber = predeterminedBoxNumber;
+    }
 }

+ 15 - 0
kmall-admin/src/main/java/com/kmall/admin/service/impl/statistics/MonthlyCustomersServiceImpl.java

@@ -209,4 +209,19 @@ public class MonthlyCustomersServiceImpl implements MonthlyCustomersService {
         return map;
     }
 
+    @Override
+    public List<MonthlySalesGrowthEntity> exportSelectedMonthData(String startMonth, String endMonth, String merchSn, int size, Integer monthNumber) {
+
+        // 查询平均销量
+        // 查询所选月份总销量
+        List<MonthlySalesGrowthEntity> avgSalesList = monthlyCustomersDao.queryAvgSales(startMonth,endMonth,merchSn,size,monthNumber);
+
+        // 查询总库存 = 店铺库存 + 园区库存 + 在途库存
+        // 1.查询店铺库存+园区库存   mall_product_store_rela 表  sku  shopNumber
+        // 2.查询在途库存  mall_goods_transport_info_detail 表
+        // 计算订货量
+
+        return avgSalesList;
+    }
+
 }

+ 4 - 0
kmall-admin/src/main/java/com/kmall/admin/service/statistics/MonthlyCustomersService.java

@@ -1,5 +1,6 @@
 package com.kmall.admin.service.statistics;
 
+import com.kmall.admin.entity.MonthlySalesGrowthEntity;
 import com.kmall.admin.entity.WechatFollowersEntity;
 
 import java.util.List;
@@ -27,4 +28,7 @@ public interface MonthlyCustomersService {
     List<Map<String,Object>> salesByCategory(String startMonth, String endMonth, String merchSn);
 
     Map<String, Object> monthlyCategory(String startMonth, String endMonth, String merchSn,List<String> dateList);
+
+
+    List<MonthlySalesGrowthEntity> exportSelectedMonthData(String startMonth, String endMonth, String merchSn, int size, Integer monthNumber);
 }

+ 58 - 0
kmall-admin/src/main/resources/mybatis/mapper/statistics/MonthlyCustomersDao.xml

@@ -205,6 +205,64 @@
 		GROUP BY
 			cg.parent_id,DATE_FORMAT(o.pay_time,'%Y-%m')
 	</select>
+    <select id="queryAvgSales" resultType="com.kmall.admin.entity.MonthlySalesGrowthEntity">
+		select
+			sku ,goodsName,total as totalNumber , saletime as salesMonth , avgSalesNumber , goodsNumber, stockNumber ,number, (goodsNumber + stockNumber + number) as totalCount,
+			if(avgSalesNumber * #{monthNumber} &lt; ((goodsNumber + stockNumber + number) - avgSalesNumber*#{size}) ,
+			avgSalesNumber * #{monthNumber},
+			((goodsNumber + stockNumber + number) - avgSalesNumber*#{size}))  as predeterminedNumber
+		from (
+
+			SELECT
+			sku,sum( number ) total ,DATE_FORMAT(og.create_time,'%Y-%m') saletime,
+			(
+			select
+			sum(mog.number)/#{size} as avgSalesNumber
+			FROM
+			mall_order_goods mog
+			where
+			DATE_FORMAT(mog.create_time,'%Y-%m') &gt;= #{startMonth}
+			and DATE_FORMAT(mog.create_time,'%Y-%m') &lt;= #{endMonth}
+			and mog.sku = og.sku
+
+			group by sku
+			) as avgSalesNumber,
+			IFNULL((
+			select g.goods_number
+			from mall_goods g
+			where g.sku = og.sku
+			),0) as goodsNumber,
+			IFNULL((
+			select sum(r.stock_num)
+			from mall_product_store_rela r
+			where r.sku = og.sku
+			),0) stockNumber,
+			IFNULL((
+			select sum(d.num)
+			from mall_goods_transport_info_detail d
+			where d.sku = og.sku
+			),0) as number,
+			og.goods_name as goodsName
+			FROM
+			mall_order o
+			LEFT JOIN mall_order_goods og ON o.id = og.order_id
+			LEFT JOIN mall_merch m ON o.merch_sn = m.merch_sn
+			<where>
+				o.is_onffline_order = '1'
+				AND o.order_biz_type = '10'
+				AND o.pay_status = '2'
+				AND DATE_FORMAT(og.create_time,'%Y-%m') &gt;= #{startMonth}
+				and DATE_FORMAT(og.create_time,'%Y-%m') &lt;= #{endMonth}
+				<if test="merchSn != null">
+					and m.merch_sn = #{merchSn}
+				</if>
+			</where>
+			group by sku,DATE_FORMAT(og.create_time,'%Y-%m')
+
+		) t
+
+
+	</select>
 
 
 </mapper>

+ 57 - 0
kmall-admin/src/main/webapp/WEB-INF/page/sale/monthlyCustomers2.html

@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Monthly Customers & Avg Basket</title>
+    #parse("sys/header.html")
+    <style>
+        .coldiv {
+            background-color: #f8f8f9;
+        }
+
+        body {
+            color: #515a6e;
+        }
+
+        #refreshTime, #storeId, #categoryId {
+            width: 100px;
+        }
+
+        #merchSn {
+            width: 300px;
+        }
+
+        i {
+            font-size: 20px;
+        }
+
+        input {
+            border: 1px #dcdee2 solid;
+            border-radius: 5px;
+            outline-color: #5cadff;
+        }
+    </style>
+</head>
+<body>
+<!--<div id="rrapp" v-cloak>-->
+    <header class="main-header">
+        <div class="container-fluid  coldiv">
+            <div class="row" style="border:0;margin-bottom:10px">
+            <span>日期:</span>
+            <input type="month" name="startMonth" id="startMonth"/>&nbsp;
+            <input type="month" name="endMonth" id="endMonth" />&nbsp;
+            <input type="button" name="queryButton" value="导出选中的数据" onclick="exportSelectedMonthData()" />
+            <input type="number" name="monthNumber" id="monthNumber">;
+            </div>
+        </div>
+    </header>
+    <div class="row">
+        <div class="col-md-12  col-sm-12  col-xs-12 charts6">
+<!--            <div id="main3" style="height: 200px;"></div>-->
+        </div>
+    </div>
+    <script src="${rc.contextPath}/js/sale/echarts.js"></script>
+    <script src="${rc.contextPath}/js/sale/monthlyCustomers2.js"></script>
+<!--</div>-->
+</body>
+</html>

+ 509 - 0
kmall-admin/src/main/webapp/js/sale/monthlyCustomers2.js

@@ -0,0 +1,509 @@
+// $(function () {
+//     var data = {
+//         "echatX": [
+//             "2019-07-02",
+//             "2019-07-03",
+//             "2019-07-04",
+//             "2019-07-05",
+//             "2019-07-06",
+//             "2019-07-07",
+//             "2019-07-08",
+//             "2019-07-09",
+//             "2019-07-10",
+//             "2019-07-11",
+//             "2019-07-12",
+//             "2019-07-13",
+//             "2019-07-14",
+//             "2019-07-15"
+//         ],
+//         "echatY": [
+//             501,210,123,333,445,157,151,369,101,101,350,435,153,100
+//         ],
+//         "echatY2": [
+//             80,40,13,36,57,77,41,39,61,31,60,73,33,50
+//         ],
+//         "echatY3": [
+//             5091,2210,1233,3133,4415,1517,1511,3619,1101,1011,3510,4315,1513,1100
+//         ],
+//         "echatY4": [
+//             501,210,123,333,445,157,151,369,101,101,350,435,153,100
+//         ],
+//         "peopleTotal":15,"peopleOnline":4,"peopleOutline":12,"ranges":[]
+//     };
+//     dFun(data.echatX, data.echatY, data.echatY2,data.echatY3,data.echatY4);
+//
+//
+// });
+// var myChart;
+// // 基于准备好的dom,初始化echarts实例
+// var dChart = echarts.init(document.getElementById('main3'));
+// // 指定图表的配置项和数据
+// function dFun(dateList, totalNumberList, totalSalesList,taotalCustomersList,avgBasketSaleList) {
+//     dChart.setOption({
+//         // title: {
+//         //     left: 'left',
+//         //     text: '概率',
+//         //     show: false
+//         // },
+//         tooltip: {
+//             trigger: 'axis',
+//             // formatter: '{a}:{c}',
+//             axisPointer: {
+//                 type: 'shadow',
+//                 crossStyle: {
+//                     color: '#999'
+//                 }
+//             }
+//         },
+//         grid: {
+//             show: false,
+//             left: '3%',
+//             right: '4%',
+//             bottom: '10%'
+//         },
+//         // legend: {
+//         //     show: true,
+//         //     selectedMode: 'single', // 设置显示单一图例的图形,点击可切换
+//         //     bottom: 10,
+//         //     left: 50,
+//         //     textStyle: {
+//         //         color: '#666',
+//         //         fontSize: 12
+//         //     },
+//         //     itemGap: 20,
+//         //     inactiveColor: '#ccc'
+//         // },
+//         xAxis: {
+//             // splitLine: {     show: false   },
+//             type: 'category',
+//             data: dateList,
+//             axisPointer: {
+//                 type: 'shadow'
+//             },
+//             // 改变x轴颜色
+//             axisLine: {
+//                 lineStyle: {
+//                     color: '#00a2e2',
+//                     width: 1, // 这里是为了突出显示加上的
+//                 }
+//             },
+//             axisTick: {
+//                 show: true,
+//                 interval: 0
+//             },
+//         },
+//         // 设置两个y轴,左边显示数量,右边显示概率
+//         yAxis: [{
+//             splitLine: {     show: false   },
+//             type: 'value',
+//             name: '',
+//             // max: 10000,
+//             // min: 0,
+//             // show: true,
+//             // interval: 1000,
+//             // 改变y轴颜色
+//             axisLine: {
+//                 lineStyle: {
+//                     color: '#00a2e2',
+//                     width: 1, // 这里是为了突出显示加上的
+//                 }
+//             },
+//         }, // 右边显示概率
+//         {
+//             splitLine: {     show: false   },
+//             type: 'value',
+//             name: '客单价',
+//             // min: 0,
+//             // max: 100,
+//             // interval: 10,
+//             // 改变y轴颜色
+//             axisLine: {
+//                 lineStyle: {
+//                     color: '#00a2e2',
+//                     width: 1, // 这里是为了突出显示加上的
+//                 }
+//             }
+//         }],
+//         // 每个设备分数量、概率2个指标,只要让他们的name一致,即可通过,legeng进行统一的切换
+//         series: [{
+//             name: 'Units Sold',
+//             type: 'bar',
+//             symbol: 'circle', // 折线点设置为实心点
+//             symbolSize: 4, // 折线点的大小
+//             data: totalNumberList,
+//             barWidth: '20%',
+//
+//         },{
+//             name: 'Sales',
+//             type: 'bar',
+//             symbol: 'circle', // 折线点设置为实心点
+//             symbolSize: 4, // 折线点的大小
+//             data: totalSalesList,
+//             barWidth: '20%',
+//
+//         },{
+//             name: 'Customers',
+//             type: 'bar',
+//             symbol: 'circle', // 折线点设置为实心点
+//             symbolSize: 4, // 折线点的大小
+//             data: taotalCustomersList,
+//             barWidth: '20%',
+//
+//         },
+//             {
+//             //折线
+//             name: 'Average Basket Sale',
+//             type: 'line',
+//             symbol: 'circle', // 折线点设置为实心点
+//             symbolSize: 6, // 折线点的大小
+//             yAxisIndex: 1, // 这里要设置哪个y轴,默认是最左边的是0,然后1,2顺序来。
+//             data: avgBasketSaleList,
+//             symbolSize: 10,
+//             itemStyle: {
+//                 normal: {
+//                     color: "#DDA0DD"
+//                 }
+//             }
+//
+//         },
+//
+//         ]
+//
+//     });
+// }
+
+function queryMonthly(){
+    var startMonth = document.getElementById("startMonth").value;
+    var endMonth = document.getElementById("endMonth").value;
+
+    var param = {
+        startMonth:startMonth,
+        endMonth:endMonth
+    };
+    console.log(param);
+    // 折线图
+    $.ajax({
+        url: "../monthly/customersQuery",
+        data: param,
+        contentType:"application/x-www-form-urlencoded",
+        type: 'POST',
+        success: function(data) {
+            console.log(JSON.stringify(data))
+            // dFun(data.dateList, data.totalNumberList, data.totalSalesList,data.taotalCustomersList,data.avgBasketSaleList);
+
+        },
+    });
+
+}
+
+function exportMonthly(){
+    var startMonth = document.getElementById("startMonth").value;
+    var endMonth = document.getElementById("endMonth").value;
+
+    var params = {
+        startMonth:startMonth,
+        endMonth:endMonth
+    };
+    console.log(params);
+    exportFile('#rrapp', '../monthly/monthlySalesGrowthExport2', params);
+
+}
+
+
+function exportSelectedMonthData(){
+    var startMonth = document.getElementById("startMonth").value;
+    var endMonth = document.getElementById("endMonth").value;
+    var monthNumber = document.getElementById("monthNumber").value;
+
+    var param = {
+        startMonth:startMonth,
+        endMonth:endMonth,
+        monthNumber:monthNumber
+    };
+    console.log(param+321313112);
+    exportFile('#rrapp', '../monthly/exportSelectedMonthData', param);
+    // $.ajax({
+    //     url: "../monthly/exportSelectedMonthData",
+    //     data: param,
+    //     contentType:"application/x-www-form-urlencoded",
+    //     type: 'POST',
+    //     success: function(data) {
+    //         console.log(JSON.stringify(data))
+    //
+    //     },
+    // });
+}
+
+
+
+let vm = new Vue({
+    el: '#rrapp',
+    data: {
+        date: '',
+        refreshTime: 10,
+        type: 'store',
+        refreshCount:0,
+
+        storeId: '',
+        merchSn: '',
+        merchName: '',
+        storeName: '',
+        salesDate: '',
+        totalSales: '',
+        actualSales: '',
+        preferentialLoss: '',
+        totalCost: '',
+        grossProfit: '',
+        grossProfitRatio: '',
+        proportion: '',
+        guestNumber: '',
+        guestUnitPrice: '',
+        lastSalesTime: '',
+        categoryId: '',
+        categoryName: '',
+
+        showList: false,
+        compareDate: '',//比较日期
+        storeId2: '',
+        merchSn2: '',
+        merchName2: '',
+        storeName2: '',
+        salesDate2: '',
+        totalSales2: '',
+        actualSales2: '',
+        preferentialLoss2: '',
+        totalCost2: '',
+        grossProfit2: '',
+        grossProfitRatio2: '',
+        proportion2: '',
+        guestNumber2: '',
+        guestUnitPrice2: '',
+        lastSalesTime2: '',
+        intervalId: 0,
+        isCompare: false,
+        compare2: '',
+
+
+        temp: {
+            date: '',
+            refreshTime: 10,
+            type: '',
+            storeId: '',
+            merchSn: '',
+            salesDate: '',
+            categoryId: ''
+        },
+
+
+        rateList: [
+            {
+                id: '0',
+                name: '含税'
+            },
+            {
+                id: '1',
+                name: '不含税'
+
+            }
+        ],
+        projectList: [
+            {
+                id: '0',
+                name: '销售总额'
+            },
+            {
+                id: '1',
+                name: '客单价'
+
+            }
+        ],
+        seriesTypeList: [
+            {
+                id: 'bar',
+                name: '垂直柱状图'
+            },
+            {
+                id: 'line',
+                name: '折线图'
+
+            },
+            {
+                id: 'pie',
+                name: '饼图'
+
+            }
+        ],
+        formatsList: [
+            {
+                id: '0',
+                name: '<全部>'
+            },
+            {
+                id: '1',
+                name: '<非全部>'
+
+            }
+        ],
+        salesList: [
+            {
+                store: {storeId: '11106', storeName: '前海店'},
+                totalSales: 43046.18,
+                actualSales: 35593.46
+            }
+        ],
+        dept: {
+            deptId: '',
+            deptName: ''
+        },
+        category: {
+            categoryId: '',
+            categoryName: ''
+        },
+        seriesList: [], //保存饼图数据
+        seriesList2: [],
+        xAxisList: {    //主要用于保存 启动刷新时的条件和数据
+            storeId: '',
+            storeName: '',
+            merchSn: '',
+            merchName: '',
+            totalSales: '',
+            actualSales: '',
+            preferentialLoss: '',
+            totalCost: '',
+            grossProfit: '',
+            grossProfitRatio: '',
+            proportion: '',
+            guestNumber: '',
+            guestUnitPrice: '',
+            lastSalesTime: '',
+
+            salesDate: '0',
+            projectSelect: '0',
+            type:''
+        },
+        dataList: [],
+        tooltip: {},
+        today:''
+    },
+    created() {
+        this.rateSelect = this.rateList[0].id;
+        this.projectSelect = this.projectList[0].id;
+        this.seriesTypeSelect = this.seriesTypeList[0].id;
+        this.formatsSelect = this.formatsList[0].id;
+    },
+    methods: {
+
+        seriesTypeSwitch: function () {
+            console.log(vm.seriesTypeSelect);
+        },
+        showEcharts: function () {
+            // 基于准备好的dom,初始化echarts实例
+            myChart = echarts.init(document.getElementById('main'));
+            myChart.clear();
+            //加载动画
+            myChart.showLoading();
+
+
+            //项目下拉框判断       6-19,饼图设置 vm.xAxisList
+            var temp = '';
+            if (vm.xAxisList.projectSelect == '0') {
+                if (vm.xAxisList.type == 'dept') {
+                    temp = '[' + vm.xAxisList.merchSn + ']' + vm.xAxisList.merchName + '/销售总额:' + vm.xAxisList.totalSales + '元(' + vm.xAxisList.salesDate + ')';
+                } else {
+                    temp = '[' + vm.xAxisList.storeId + ']' + vm.xAxisList.storeName + '/销售总额:' + vm.xAxisList.totalSales + '元(' + vm.xAxisList.salesDate + ')';
+                }
+                vm.seriesList2.push(vm.xAxisList.totalSales);
+                vm.seriesList.push({value: vm.xAxisList.totalSales, name: temp});
+
+            } else if (vm.xAxisList.projectSelect == '1') {
+                if (vm.xAxisList.type == 'dept') {
+                    temp = '[' + vm.xAxisList.merchSn + ']' + vm.xAxisList.merchName + '/客单价:' + vm.xAxisList.guestUnitPrice + '元(' + vm.xAxisList.salesDate + ')';
+                } else {
+                    temp = '[' + vm.xAxisList.storeId + ']' + vm.xAxisList.storeName + '/客单价:' + vm.xAxisList.guestUnitPrice + '元(' + vm.xAxisList.salesDate + ')';
+                }
+                vm.seriesList2.push(vm.xAxisList.guestUnitPrice);
+                vm.seriesList.push({value: vm.xAxisList.guestUnitPrice, name: temp});
+
+            }
+
+            vm.dataList = [temp];
+
+            if (vm.seriesTypeSelect == "pie") {
+                vm.seriesList2 = vm.seriesList.concat();
+            }
+
+            // console.log('vm.seriesList2');
+            // console.log(vm.seriesList2);
+
+            // 指定图表的配置项和数据
+            //销售量
+            var option = {
+                title: {
+                    // textAlign: 'right',
+                    text: 'Monthly Customers & Avg Basket',
+                    x: 'center',
+                    textStyle: {
+                        //文字颜色
+                        color: '#17233d',
+                        //字体风格,'normal','italic','oblique'
+                        fontStyle: 'normal',
+                        //字体粗细 'normal','bold','bolder','lighter',100 | 200 | 300 | 400...
+                        fontWeight: 'bold',
+                        //字体系列
+                        fontFamily: 'sans-serif',
+                        //字体大小
+                        fontSize: 28
+                    }
+                },
+                tooltip: {
+                    formatter: function (params) {
+                        return params.name;
+                    }
+                },
+                legend: {
+                    data: ['/销售总额']
+                },
+                xAxis: {
+                    data: vm.dataList,
+                    axisLabel: {
+                        interval: 0
+                    }
+                },
+                yAxis: {},
+                series: [{
+                    barMaxWidth: '20%',
+                    barWidth: '50%',
+                    radius: '55%',
+                    roseType: 'angle',
+                    type: vm.seriesTypeSelect,
+                    color: ['#dd6b66', '#759aa0'],
+                    data: vm.seriesList2
+                }]
+            };
+
+            //隐藏
+            myChart.hideLoading();
+            // 使用刚指定的配置项和数据显示图表。
+            myChart.setOption(option);
+
+        },
+        tooltipFormatter: function () {
+            if (vm.type == 'dept') {
+                return '[' + vm.merchSn + ']' + vm.merchName + '/销售总额:' + vm.totalSales + '元(' + vm.salesDate + ')';
+            }
+            return '[' + vm.storeId + ']' + vm.storeName + '/销售总额:' + vm.totalSales + '元(' + vm.salesDate + ')';
+        },
+        showTable: function (postParam) {
+
+            console.log(postParam);
+
+            $("#jqGrid").jqGrid('setGridParam', {
+                postData: postParam
+
+            }).trigger("reloadGrid").closest(".ui-jqgrid-bdiv").css({"overflow-x": "scroll"});
+        },
+        switchProjectView: function () {
+            console.log(vm.projectSelect);
+        }
+    }
+});