javaweb-青橙项目-6-81

文章目录

  • 第6章 统计分析
    • 学习目标
  • 1. 商品类目销售分析表
    • 1.1 需求分析
    • 1.2 实现思路
    • 1.3 代码实现
      • 1.3.1 类目统计SQL语句
      • 1.3.2 类目统计代码实现
      • 1.3.3 定时任务-生成统计数据
      • 1.3.4 按日期统计一级分类数据
      • 1.3.5 商品类目统计名称显示
      • 1.3.6 商品类目统计前端实现
      • 1.3.7 比例计算
    • 1.4 小结
  • 2. EChars图表插件
    • 2.1 EChars简介
    • 2.2 快速入门
      • 2.2.1 简单柱状图
      • 2.2.2 多数据的柱状图
      • 2.2.3 简单饼图
      • 2.2.4 多数据的饼图
  • 3. 商品类目销售统计(饼图)
    • 3.1 需求分析
    • 3.2 实现思路
    • 3.3 代码实现
  • 4. 流量统计
    • 4.1 相关术语
      • 4.1.1 IP
      • 4.1.2 UV
      • 4.1.3 PV
    • 4.2 百度统计
  • 5. 交易统计
    • 5.1 交易统计表
      • 5.1.1 需求分析
      • 5.1.2 实现思路
    • 5.2 漏斗图
      • 5.2.1 需求分析
      • 5.2.2 实现思路
    • 5.3 折线图
      • 5.3.1 需求分析
      • 5.3.2 实现思路

第6章 统计分析

学习目标

完成商品类目销售分析表
掌握echars图表插件的基本用法
使用echars完成商品类目销售统计饼图

1. 商品类目销售分析表

如图
交易统计分析
在这里插入图片描述
商品统计分析等等
在这里插入图片描述

1.1 需求分析

商品类目销售分析是统计一段时间内各商品分类(一级分类)的销售数量与销售额以及所占总额的比重,如下图:
目的是得出某种商品比较火,收益做好,

在这里插入图片描述

那么这个表的数据源是谁?如何得到这些需要的数据?

1.2 实现思路

(1)销售分析表数据来自订单表和订单明细表,
对订单表和订单明细表进行统计。
对两个表连接查询,然后再对某个字段聚合,
销售金额有两个字段,money(期望支付,价格*数量) paymoney(实际支付,期望支付-优惠券)
订单明细表中记录了商品的一级分类,我们按照一级分类聚合运算就可以统计出各分类的销售额。

(2)销售金额的统计要按照优惠后的金额(pay_money)进行统计。

(3)订单表和订单明细表数据量庞大,如果实时统计,统计效率将会很低,因此应该错开时差,通常是每天定时统计上一天的数据,将统计结果存储在一张表中。当用户执行管理后台的统计功能时,再对这张表进行统计,给前端返回统计结果。
存储统计结果的表结构如下:不过我认为应该加一个实时统计的按钮,毕竟谁都想知道当前的商品销售如何

既然这里只统计一级分类销售额,为什么表中还要有二级,三级分类?
这是为了顺带的数据统计,其他分析用得到
在这里插入图片描述

1.3 代码实现

1.3.1 类目统计SQL语句

按照商品一级分类、二级分类、三级分类聚合统计销售数量和销售金额,查询条件为支付状态为已支付,未删除的数据并且支付日期为某日的。
语句看着很复杂,应该分步写
先将两个表关联起来
在这里插入图片描述
从关联的表中,找到已经支付且订单未删除的
在这里插入图片描述

要统计昨天的数据,因此应该只保留昨天的,使用mysql时间函数将时间格式变为字符串格式,切除后面的具体时分秒
在这里插入图片描述

得到了昨天的所有数据,那么开始根据三个分类和时间进行分组
在这里插入图片描述

已经聚合完毕,开始得到表中的数据即可
id1,id2,id3,销售数量和,销售总额
当然,列名太丑了 ,起个别名便于看
在这里插入图片描述

SELECT oi.`category_id1`,oi.`category_id2`,oi.`category_id3`,DATE_FORMAT(o.`pay_time`,'%Y-%m-%d') count_date,SUM(oi.`num`) num,SUM(oi.`pay_money`) money
FROM tb_order_item oi,tb_order o
WHERE oi.`order_id`=o.`id` AND o.`pay_status`='1' AND o.`is_delete`='0' AND DATE_FORMAT(o.`pay_time`,'%Y-%m-%d')='2019-04-15'
GROUP BY oi.`category_id1`,oi.`category_id2`,oi.`category_id3`,DATE_FORMAT(o.`pay_time`,'%Y-%m-%d')

DATE_FORMAT是mysql提供的日期转换函数
在这里插入图片描述

1.3.2 类目统计代码实现

(1)创建实体类
上述表在数据库中新建一个即可
在代码中添加实体类,
代码自动生成器对于联合主键的表不会自动生成,

@Table(name="tb_category_report")
public class CategoryReport implements Serializable {
    @Id
    private Integer categoryId1;//1级分类
    @Id
    private Integer categoryId2;//2级分类
    @Id
    private Integer categoryId3;//3级分类
    @Id
    private Date countDate;//统计日期
    private Integer num;//销售量
    private Integer money;//销售额
    public Integer getCategoryId1() {
        return categoryId1;
    }
    public void setCategoryId1(Integer categoryId1) {
        this.categoryId1 = categoryId1;
    }
    public Integer getCategoryId2() {
        return categoryId2;
    }
    public void setCategoryId2(Integer categoryId2) {
        this.categoryId2 = categoryId2;
    }
    public Integer getCategoryId3() {
        return categoryId3;
    }
    public void setCategoryId3(Integer categoryId3) {
    this.categoryId3 = categoryId3;
        }
public Date getCountDate() {
        return countDate;
        }
public void setCountDate(Date countDate) {
        this.countDate = countDate;
        }
public Integer getNum() {
        return num;
        }
public void setNum(Integer num) {
        this.num = num;
        }
public Integer getMoney() {
        return money;
        }
public void setMoney(Integer money) {
        this.money = money;
        }
        }

(2)新建数据访问接口CategoryReportMapper
此处的语句即上面的语句
此处书写sql语句注意每行后面加空格,否则一拼接就是非法的
日期应该是活的#{date}

注意这里一定要有别名,因为对于数据对象来说,需要别名来识别数据,oi.category_id1不会被承认categoryId1
否则数据无法引入就会为空
在这里插入图片描述

public interface CategoryReportMapper extends Mapper<CategoryReport> {

    @Select("SELECT oi.`category_id1` categoryId1,oi.`category_id2` categoryId2,oi.`category_id3` categoryId3,DATE_FORMAT( o.`pay_time`,'%Y-%m-%d') countDate,SUM(oi.`num`) num,SUM(oi.`pay_money`) money " +
            "FROM tb_order_item oi,tb_order o " +
            "WHERE oi.`order_id`=o.`id` AND o.`pay_status`='1' AND o.`is_delete`='0'  AND  DATE_FORMAT( o.`pay_time`,'%Y-%m-%d')=#{date} " +
            "GROUP BY oi.`category_id1`,oi.`category_id2`,oi.`category_id3`,DATE_FORMAT( o.`pay_time`,'%Y-%m-%d')")
    public List<CategoryReport> categoryReport(@Param("date") LocalDate date);
}

(3)新建业务接口CategoryReportService

/**
 * 报表服务层接口
 */
public interface CategoryReportService {
    /**
     * 商品类目按日期统计(订单表关联查询)
     * @param date
     * @return
     */
    public List<CategoryReport> categoryReport(LocalDate date);
}

(4)新建业务实现

@Service
public class CategoryReportServiceImpl implements CategoryReportService {
    @Autowired
    private CategoryReportMapper categoryReportMapper;
    @Override
    public List<CategoryReport> categoryReport(LocalDate date) {
        return categoryReportMapper.categoryReport(date);
    }
}

(5)新建Controller
获得昨天日期扔过去

@RestController
@RequestMapping("/categoryReport")
public class CategoryReportController {
    @Reference
    private CategoryReportService categoryReportService;
    /**
     * 昨天的数据统计
     * @return
     */
    @GetMapping("/yesterday")
    public List<CategoryReport> yesterday(){
        LocalDate localDate = LocalDate.now().minusDays(1);// 得到昨天的日期
        return categoryReportService.categoryReport(localDate);
    }
}

浏览器测试: http://localhost:9101/categoryReport/yesterday.do

1.3.3 定时任务-生成统计数据

创建定时任务,每天凌晨1点统计昨天的数据,插入到tb_category_report中。
(1)CategoryReportService新增方法定义

public void createData();

(2)CategoryReportServiceImpl实现方法
获得的数据不止一条,循环遍历出来

@Transactional
public void createData() {
        LocalDate localDate = LocalDate.now().minusDays(1);// 得到昨天的日期
        List<CategoryReport> categoryReports = categoryReportMapper.categoryReport(localDate);
        for(CategoryReport categoryReport:categoryReports){
        categoryReportMapper.insert(categoryReport);
        }
        }

CategoryReportServiceImpl的service注解添加属性

@Service(interfaceClass = CategoryReportService.class)

(3)OrderTask新增方法
远程注入数据
使用功能cron定时器自动执行
很多大数据的统计与运算都在凌晨进行

@Reference
private CategoryReportService categoryReportService;
@Scheduled(cron = "0 0 1 * * ?")
public void createCategoryReportData(){
System.out.println("create Category ReportData 生成类目统计数据");
categoryReportService.createData();
}

1.3.4 按日期统计一级分类数据

此时基于得到的统计数据表再次进行计算,
我们再次对tb_category_report进行聚合运算,得出一个时间段的统计数据
只需要一级分类的数据

SELECT category_id1 categoryId1,SUM(num) num ,SUM(money) 
FROM  `tb_category_report` 
WHERE count_date >='2019-04-15'  AND count_date <='2019-04-16' GROUP BY category_id1

在这里插入图片描述

(1)在CategoryReportMapper新增方法

/**
 * 按时间段统计一级类目
 * @param date1
 * @param date2
 * @return
 */
@Select("SELECT category_id1 categoryId1,SUM(num) num ,SUM(money)
        FROM `tb_category_report` WHERE count_date>=#{date1} and count_date<=#
        {date2} GROUP BY category_id1")
        public List<Map> category1Count(@Param("date1") String date1 ,
        @Param("date2") String date2 );

(2)CategoryReportService新增方法

/**
 * 一级类目统计
 * @param date1
 * @param date2
 * @return
 */
public List<Map> category1Count(String date1 , String date2 );

(3)CategoryReportServiceImpl实现方法

@Override
public List<Map> category1Count(String date1, String date2) {
        return categoryReportMapper.category1Count(date1,date2);
        }

(4)CategoryReportController新增方法

/**
 * 统计一级类目
 * @param date1
 * @param date2
 * @return
 */
@GetMapping("/category1Count")
public List<Map> category1Count(String date1, String date2){
        return categoryReportService.category1Count(date1,date2);
        }

数据查询完成在这里插入图片描述

1.3.5 商品类目统计名称显示

当前的统计结果中,只有分类id,没有分类名称。而最终的结果是要显示分类名称的,如
何实现呢?
(1)创建视图
分类名称所在的分类表在商品数据库中,而当前我们连接的是订单数据库,这种情况下
我们需要在订单数据库中创建视图,让其得到一级分类列表的id与名字。
在order订单数据库,如何查询goods商品数据库呢?
库名.表名
然而直接操作其他数据库的数据看起来将会非常麻烦。因此应该为其创建一个视图,这样操作视图就如同操作本数据库的表一样,但是效果却很好
但是表中只需要部分数据,比如一级分类的id和name,取之于蓝而胜于蓝得到新表,虚拟的视图

CREATE VIEW v_category AS
SELECT id,NAME FROM qingcheng_goods.`tb_category` WHERE parent_id=0

(2)改造之前的sql语句
让得到的视图和得到的统计表关联,得到新的数据表

SELECT category_id1 categoryId1,c.name categoryName,SUM(num) num,SUM(money) money
FROM tb_category_report r,v_category c
WHERE r.category_id1=c.id AND count_date>='2019-04-15' AND count_date<='2019-04-17'
GROUP BY category_id1,c.name

在这里插入图片描述

(3)修改CategoryReportMapper接口category1Count方法的sql语句

@Select("SELECT category_id1 categoryId1,c.name categoryName,SUM(num)
        num, SUM(money) money " +
        "FROM tb_category_report r,v_category1 c " +
        "WHERE r.category_id1=c.id AND count_date>=#{date1} AND
        count_date<=#{date2} " +
        "GROUP BY category_id1,c.name")
public List<Map> category1Count( @Param("date1") String
        date1,@Param("date2") String date2);

此时名称已经绑定,到此销售数据的统计后端已经完成
在这里插入图片描述
接下来使用前端,展示分析结果

1.3.6 商品类目统计前端实现

(1)创建report/categoryReport.html页面,引入样式和js

<!‐‐ 引入样式 ‐‐>
<link rel="stylesheet" href="https://unpkg.com/element‐ui/lib/theme‐
        chalk/index.css">
<link rel="stylesheet" href="../plugins/font‐awesome/css/font‐
        awesome.min.css">
<link rel="stylesheet" href="../css/style.css">

引入util.js是因为要用到处理日期格式方法

<script src="/js/util.js"></script>
<script src="/js/vue.js"></script>
<script src="/js/axios.js"></script>
<script src="/js/elementui.js"></script>

(2)创建表格
从element ui网站上找到表格控件

<div id="app">
<el‐table :data="tableData" border style="width: 100%">
<el‐table‐column prop="categoryName" label="一级分类" width="200">
</el‐table‐column>
<el‐table‐column prop="num" label="数量" width="200"></el‐table‐
        column>
<el‐table‐column prop="money" label="销售额" width="200"></el‐table‐
        column>
</el‐table>
</div>

(3)创建日期范围控件
从element ui网站上找到日期选择器
v‐model=“dateRange”
绑定变量

这里添加了一个事件, @change="fetchData()
代表,当日期发生变化的时候就会自动触发下面的脚本

<el-date-picker
            v-model="dateRange"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            @change="fetchData()">
    </el-date-picker>

(4)编写脚本

<script>
new Vue({
el: '#app',
data(){
return {
tableData: [],
dateRange:[]
}
},
methods:{
fetchData (){
//查询统计分析数据 
let date1=this.dateRange[0].Format("yyyy‐MM‐dd");
let date2=this.dateRange[1].Format("yyyy‐MM‐dd");
axios.get(`/categoryReport/category1Count.do?date1=${date1}&date2=${date2}`).then(response => {
this.tableData = response.data;
});
}
}
})
</script>

暂时忽略饼形图,日期变化时自动触发
选择日期区间
在这里插入图片描述

在这里插入图片描述

1.3.7 比例计算

需求:统计表中显示销售数量比例与销售金额比例,销售金额单位转换为元。数据库中保存的是元,/100转化为元
思路:得到报表数据后,通过循环计算总销售数量和总销售额,在表格中通过模板列计算得出比例。
得到一列中所有的数量和,然后除法
得到一列中所有的金额和,然后除法

表格新增
如上图,对于比例不要小数
{{(scope.row.num/totalNum*100).toFixed(0)}}%
销售额保留两位
{{(scope.row.money/100).toFixed(2)}}

 <el-table
            :data="tableData"
            border
            style="width: 100%">
        <el-table-column
                prop="categoryName"
                label="分类名称"
                width="200">
        </el-table-column>
        <el-table-column
                prop="num"
                label="销售量"
                width="200">
        </el-table-column>
        <el-table-column
                label="数量比例"
                width="200">
            <template slot-scope="scope">
                {{(scope.row.num/totalNum*100).toFixed(0)}}%
            </template>
        </el-table-column>

        <el-table-column
                label="销售额"
                width="200">
            <template slot-scope="scope">
                {{(scope.row.money/100).toFixed(2)}}
            </template>
        </el-table-column>
        <el-table-column
                label="金额比例"
                width="200">
            <template slot-scope="scope">
                {{(scope.row.money/totalMoney*100).toFixed(0)}}%
            </template>
        </el-table-column>

    </el-table>

计算脚本哪里
初始化总额为0

data(){
            return {
                tableData:[],
                dateRange:[],
                totalNum:0,
                totalMoney:0
            }
        },

fetchdata每次调用时都清零,防止日期变化时数值自动累加
累加数量

  //计算总销售数量和总销售金额
                    this.totalNum=0;
                    this.totalMoney=0;
                    for(let i=0;i<this.tableData.length;i++){
                        this.totalNum+=this.tableData[i].num;
                        this.totalMoney+=this.tableData[i].money;
                    }

1.4 小结

分组聚合SQL语句的编写–对于复杂语句书写思路
跨库查询
视图的创建与使用
通用mapper自定义方法
定时任务
日期范围控件(前端)

2. EChars图表插件

已经有了表和比例数据,但是不够直观

2.1 EChars简介

ECharts,百度开源的图表插件。一个使用 JavaScript 实现的开源可视化库,可以流
畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,
Firefox,Safari等),底层依赖轻量级的矢量图形库 ZRender,提供直观,交互丰富,
可高度个性化定制的数据可视化图表。
ECharts 提供了常规的折线图、柱状图、散点图、饼图、K线图,用于统计的盒形
图,用于地理数据可视化的地图、热力图、线图,用于关系数据可视化的关系
图、treemap、旭日图,多维数据可视化的平行坐标,还有用于 BI 的漏斗图,仪表盘,
并且支持图与图之间的混搭。
详见EChars官网 https://echarts.baidu.com/
界面非常炫酷
3d地图都有
在这里插入图片描述

2.2 快速入门

2.2.1 简单柱状图

echars组件有三种版本,完全,通用,精简,功能随着减少
(1)新建页面,引入js

<script src="/js/echarts.common.min.js"></script>

(2)在页面放置 div用于显示报表

<div id="main" style="width: 600px;height:400px;"></div>

(3)编写js代码
标题,图例(控制图是否显示的小控件),x轴设计,y轴,具体的图表数据,图标类型

// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
        var option = {
        title: {
        text: 'ECharts 入门示例'
        },
        tooltip: {},
        legend: {
        data:['销量']
        },
        xAxis: {
        data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
        },
        yAxis: {},
        series: [{
        name: '销量',
        type: 'bar',
        data: [5, 20, 36, 10, 10, 20]
        }]
        };
// 使用刚指定的配置项和数据显示图表。
        myChart.setOption(option);

2.2.2 多数据的柱状图

单数据柱状图往往不能满足需求,对于单一x轴坐标可能有多维类型

<!DOCTYPE html>
<html>
<head>
<meta charset="utf‐8">
<title>ECharts</title>
<script src="echarts.common.min.js"></script>
</head>
<body>
<!‐‐ 为 ECharts 准备一个具备大小(宽高)的 DOM ‐‐>
<div id="main" style="width: 600px;height:400px;"></div>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
        var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
        var option = {
        title: {
        text: 'ECharts 入门示例'
        },
        tooltip: {},
        legend: {
        data:['销量','销售额']
        },
        xAxis: {
        data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
        },
        yAxis: {},
        series: [{
        name: '销量',
        type: 'bar',
        data: [5, 20, 36, 10, 10, 20]
        },{
        name: '销售额',
        type: 'bar',
        data: [30, 33, 56, 88, 23, 55]
        }]
        };
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
</body>
</html>

如果想要看某一类型数据,关闭其他图例即可
在这里插入图片描述

2.2.3 简单饼图

如果有疑问看官方文档,每个配置项都有说明
标题,主,副
链接
提示框组件,鼠标悬浮自动点亮,有坐标轴,空等
图例,控制竖直还是水平显示,位置(像素,四大方向,百分比),图例内容
指定数据显示图形形式,图形的位置,名字,部分显示内容,百分比占用
图形的高亮显示,当点击时显示
使用官方案例少量改动即可

<!DOCTYPE html>
<html>
<head>
<meta charset="utf‐8">
<title>ECharts</title>
<script src="echarts.common.min.js"></script>
</head>
<body>
<!‐‐ 为 ECharts 准备一个具备大小(宽高)的 DOM ‐‐>
<div id="main" style="width: 600px;height:400px;"></div>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
        var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
        option = {
        title : {
        text: '某站点用户访问来源',
        subtext: '纯属虚构',
        x:'center'
        },
        tooltip : {
        trigger: 'item',
        formatter: "{a} <br/>{b} : {c} ({d}%)"
        },
        legend: {
        orient: 'vertical',
        left: 'left',
        data: ['直接访问','邮件营销','联盟广告','视频广告','搜索引
        擎']
        },
        series : [
        {
        name: '访问来源',
        type: 'pie',
        radius : '55%',
        center: ['50%', '60%'],
        data:[
        {value:335, name:'直接访问'},
{value:310, name:'邮件营销'},
        {value:234, name:'联盟广告'},
        {value:135, name:'视频广告'},
        {value:1548, name:'搜索引擎'}
        ],
        itemStyle: {
        emphasis: {
        shadowBlur: 10,
        shadowOffsetX: 0,
        shadowColor: 'rgba(0, 0, 0, 0.5)'
        }
        }
        }
        ]
        };
// 使用刚指定的配置项和数据显示图表。
        myChart.setOption(option);
</script>
</body>
</html>

在这里插入图片描述

配置项详解:

  1. title 标题组件
    title.text 主标题文本
    title.subtext 副标题文本
    title.x (title.textAlign) 整体(包括 text 和 subtext)的水平对齐 可选
    值: ‘auto’ 、 ‘left’ 、 ‘right’ 、 ‘center’ 。
  2. tooltip 提示框组件
    tooltip.trigger 触发类型
    可选:
    ‘item’
    数据项图形触发,主要在散点图,饼图等无类目轴的图表中使用。
    ‘axis’
    坐标轴触发,主要在柱状图,折线图等会使用类目轴的图表中使用。
    ‘none’
    什么都不触发。
    tooltip.formatter 提示框浮层内容格式器,支持字符串模板和回调函数两种形式
    模板变量有 {a} , {b} , {c} , {d} ,分别表示系列名,数据名,数据值等。 不同图表
    类型下的 {a} , {b} , {c} , {d} 含义不一样。 其中变量 {a} , {b} , {c} , {d} 在不
    同图表类型下代表数据含义为:
    折线(区域)图、柱状(条形)图、K线图 : {a} (系列名称), {b} (类目
    值), {c} (数值), {d} (无)
    散点图(气泡)图 : {a} (系列名称), {b} (数据名称), {c} (数值数
    组), {d} (无)
    地图 : {a} (系列名称), {b} (区域名称), {c} (合并数值), {d} (无)
    饼图、仪表盘、漏斗图: {a} (系列名称), {b} (数据项名称), {c} (数
    值), {d} (百分比)
  3. legend 图例组件
    legend.orient 图例列表的布局朝向
    可选:
    ‘horizontal’ 水平布局
    ‘vertical’ 垂直布局
    legend.left 图例组件离容器左侧的距离。
    left 的值可以是像 20 这样的具体像素值,可以是像 ‘20%’ 这样相对于容器高宽的百
    分比,也可以是 ‘left’ , ‘center’ , ‘right’ 。
    如果 left 的值为 ‘left’ , ‘center’ , ‘right’ ,组件会根据相应的位置自动对齐。
    legend.data 图例的数据数组。
  4. series 系列列表
    series[i]-pie.radius 饼图的半径。可以为如下类型:
    number :直接指定外半径值。
    string :例如, ‘20%’ ,表示外半径为可视区尺寸(容器高宽中较小一项)的 20%
    长度。
    Array. :数组的第一项是内半径,第二项是外半径。每一项遵从上
    述 number string 的描述。
    series[i]-pie.center 饼图的中心(圆心)坐标
    数组的第一项是横坐标,第二项是纵坐标。
    支持设置成百分比,设置成百分比时第一项是相对于容器宽度,第二项是相对于容器高
    度。
    series[i]-pie.itemStyle 图形的样式
    series[i]-pie.emphasis 高亮的扇区和标签样式。
    series[i]-pie.emphasis.itemStyle.shadowBlur 图形阴影的模糊大小
    series[i]-pie.emphasis.itemStyle.shadowColor 阴影颜色
    series[i]-pie.emphasis.itemStyle.shadowOffsetX 阴影水平方向上的偏移距离

2.2.4 多数据的饼图

道理相似,有时一个饼图不足以显示全部数据,因此需要多个饼图

option = {
        title : {
        text: '商品类目销售分析',
        subtext: '这是个例子',
        x:'center'
        },
        tooltip : {
        trigger: 'item',
        formatter: "{a} <br/>{b} : {c} ({d}%)"
        },
        legend: {
        orient: 'vertical',
        left: 'left',
        data: ['水果','蔬菜','家电','数码','服装']
        },
        series : [
        {
        name: '销售量',
        type: 'pie',
        radius : '35%',
        center: ['30%', '50%'],
        data:[
        {value:335, name:'水果'},
        {value:310, name:'蔬菜'},
        {value:234, name:'家电'},
        {value:135, name:'数码'},
        {value:1548, name:'服装'}
        ],
        itemStyle: {
        emphasis: {
        shadowBlur: 10,
        shadowOffsetX: 0,
        shadowColor: 'rgba(0, 0, 0, 0.5)'
        }
        }
        },
        {
        name: '销售额',
        type: 'pie',
        radius : '35%',
center: ['80%', '50%'],
        data:[
        {value:2003, name:'水果'},
        {value:2310, name:'蔬菜'},
        {value:4434, name:'家电'},
        {value:1125, name:'数码'},
        {value:1448, name:'服装'}
        ],
        itemStyle: {
        emphasis: {
        shadowBlur: 10,
        shadowOffsetX: 0,
        shadowColor: 'rgba(0, 0, 0, 0.5)'
        }
        }
        }
        ]
        };

注意:这两个饼图的圆点坐标不要重复。
在这里插入图片描述

3. 商品类目销售统计(饼图)

3.1 需求分析

根据商品类目销售分析表生成饼图,
左侧的饼图为销售量统计分析图,右侧的饼图为销售额统计分析图。
在这里插入图片描述

3.2 实现思路

(1)EChars有自己的数据格式,我们可以将后端返回的商品类目销售分析表的数据进行整理,得到EChars需要的数据格式。
(2)使用EChars的饼图控件。

3.3 代码实现

(1)页面引入js

<script src="/js/echarts.common.min.js"></script>

(2)在页面放置 div用于显示报表

<div id="main" style="width: 600px;height:400px;"></div>

(3)修改fetchData方法,在回调处添加以下代码
先获得绘制饼图所需的数据组
然后将数据放置在饼图的数据源处即可

  let legendData=[];//图例
                    let numData=[];//销售量数据
                    let moneyData=[];//销售额数据
                    for(let i=0;i<this.tableData.length;i++){
                        legendData.push( this.tableData[i].categoryName  );
                        numData.push( { name:this.tableData[i].categoryName   ,value:this.tableData[i].num  } );
                        moneyData.push( { name:this.tableData[i].categoryName   ,value:this.tableData[i].money  } );
                    }

                    //创建饼图
                    let myChart = echarts.init(document.getElementById('main'));
                    let option = {
                        title : {
                            text: '商品类目销售分析',
                            subtext: '',
                            x:'center'
                        },
                        tooltip : {
                            trigger: 'item',
                            formatter: "{a} <br/>{b} : {c} ({d}%)"
                        },
                        legend: {
                            orient: 'vertical',
                            left: 'left',
                            data: legendData
                        },
                        series : [
                            {
                                name: '销售量',
                                type: 'pie',
                                radius : '35%',
                                center: ['30%', '50%'],
                                data:numData,
                                itemStyle: {
                                    emphasis: {
                                        shadowBlur: 10,
                                        shadowOffsetX: 0,
                                        shadowColor: 'rgba(0, 0, 0, 0.5)'
                                    }
                                }
                            },
                            {
                                name: '销售额',
                                type: 'pie',
                                radius : '35%',
                                center: ['80%', '50%'],
                                data:moneyData,
                                itemStyle: {
                                    emphasis: {
                                        shadowBlur: 10,
                                        shadowOffsetX: 0,
                                        shadowColor: 'rgba(0, 0, 0, 0.5)'
                                    }
                                }
                            }
                        ]
                    };

                    // 使用刚指定的配置项和数据显示图表。
                    myChart.setOption(option);

在这里插入图片描述

4. 流量统计

4.1 相关术语

4.1.1 IP

公网ip,因此私网下的多个人访问被视为同一个人,统计不精准
IP(独立IP),即Internet Protocol,这里是指独立IP数,独立IP是指不同IP地址的计算机
访问网站时被计的总次数。独立IP数是衡量网站流量的一个重要指标。一般一天内
(00:00-24:00)相同IP地址的客户端访问网站页面只会被计为一次. 假设公司很多人在局
域网中同时打开网站,此时只能算一个独立IP。

4.1.2 UV

根据客户端判断人流量,较为精准,但是如果多个人使用同一台设备,也会有误差
UV(独立访客)即Unique Visitor,同一个客户端(PC或移动端)访问网站被计为一
个访客。一天(00:00-24:00)内相同的客户端访问同一个网站只计一次UV。UV一般是以客
户端Cookie等技术作为统计依据的,实际统计会有误差。

4.1.3 PV

页面被点击一次视为一次访问
PV(访问量)即Page View ,中文翻译为页面浏览,即页面浏览量或点击量,不管客户
端是不是不同,也 不管IP是不是不同,用户只要访问网站页面就会被计算PV,一次计一
个PV。

4.2 百度统计

点击量可以不用自己统计,而是交给百度

全球最大的中文网站流量分析平台,登陆系统后按照系统说明完成代码添加,
百度统计便可马上收集数据,为用户提高投资回报率提供决策依据。帮助用户跟踪网站的真实流量,并优化网站的运营决策。
https://tongji.baidu.com/web/welcome/login
点击来源客户端,uv,pv,ip,点击的页面等等

实际生产中,可以通过百度提供的api,将其数据导入自己的网站中展现即可

5. 交易统计

5.1 交易统计表

5.1.1 需求分析

实现交易数据统计,以表格形式展现浏览人数 下单人数 订单数 下单件数 有效订单
数 下单金额 退款金额 付款人数 付款订单数 付款件数 付款金额

在这里插入图片描述

5.1.2 实现思路

(1)创建交易统计表,用于存储每天的统计结果(表结构定义)
(2)编写代码,创建定时任务,在凌晨1点执行统计,将统计结果插入到交易统计表
(3)编写代码,实现对交易统计表的聚合运算(按时间段查询)
(4)浏览人数可以通过调用“百度统计”API获取。

5.2 漏斗图

5.2.1 需求分析

根据浏览人数、下单人数和付款人数构建漏斗图。见静态原型

在这里插入图片描述

5.2.2 实现思路

(1)使用EChars的漏斗图控件实现此功能,接受的数据是上一步统计出来的浏览人数、
下单人数和付款人数
(2)下单转化率= 下单人数/浏览人数 用户购买欲望如何
(3)付款转化率=付款人数/下单人数 是不是付款流程有问题
(4)成交转化率=付款人数/浏览人数

5.3 折线图

5.3.1 需求分析

根据某一时间段的交易数据,展现折线图。交易数据包括付款金额、退款金额、付款人
数、付款件数、下单转化率、付款转化率、成交转化率

在这里插入图片描述

5.3.2 实现思路

使用EChars的折线图可以实现

热门文章

暂无图片
编程学习 ·

gdb调试c/c++程序使用说明【简明版】

启动命令含参数&#xff1a; gdb --args /home/build/***.exe --zoom 1.3 Tacotron2.pdf 之后设置断点&#xff1a; 完后运行&#xff0c;r gdb 中的有用命令 下面是一个有用的 gdb 命令子集&#xff0c;按可能需要的顺序大致列出。 第一列给出了命令&#xff0c;可选字符括…
暂无图片
编程学习 ·

高斯分布的性质(代码)

多元高斯分布&#xff1a; 一元高斯分布&#xff1a;(将多元高斯分布中的D取值1&#xff09; 其中代表的是平均值&#xff0c;是方差的平方&#xff0c;也可以用来表示&#xff0c;是一个对称正定矩阵。 --------------------------------------------------------------------…
暂无图片
编程学习 ·

强大的搜索开源框架Elastic Search介绍

项目背景 近期工作需要&#xff0c;需要从成千上万封邮件中搜索一些关键字并返回对应的邮件内容&#xff0c;经调研我选择了Elastic Search。 Elastic Search简介 Elasticsearch &#xff0c;简称ES 。是一个全文搜索服务器&#xff0c;也可以作为NoSQL 数据库&#xff0c;存…
暂无图片
编程学习 ·

Java基础知识(十三)(面向对象--4)

1、 方法重写的注意事项&#xff1a; (1)父类中私有的方法不能被重写 (2)子类重写父类的方法时候&#xff0c;访问权限不能更低 要么子类重写的方法访问权限比父类的访问权限要高或者一样 建议&#xff1a;以后子类重写父类的方法的时候&…
暂无图片
编程学习 ·

Java并发编程之synchronized知识整理

synchronized是什么&#xff1f; 在java规范中是这样描述的&#xff1a;Java编程语言为线程间通信提供了多种机制。这些方法中最基本的是使用监视器实现的同步(Synchronized)。Java中的每个对象都是与监视器关联&#xff0c;线程可以锁定或解锁该监视器。一个线程一次只能锁住…
暂无图片
编程学习 ·

计算机实战项目、毕业设计、课程设计之 [含论文+辩论PPT+源码等]小程序食堂订餐点餐项目+后台管理|前后分离VUE[包运行成功

《微信小程序食堂订餐点餐项目后台管理系统|前后分离VUE》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 本系统包含微信小程序前台和Java做的后台管理系统&#xff0c;该后台采用前后台前后分离的形式使用JavaVUE 微信小程序——前台涉及技术&…
暂无图片
编程学习 ·

SpringSecurity 原理笔记

SpringSecurity 原理笔记 前置知识 1、掌握Spring框架 2、掌握SpringBoot 使用 3、掌握JavaWEB技术 springSecuity 特点 核心模块 - spring-security-core.jar 包含核心的验证和访问控制类和接口&#xff0c;远程支持和基本的配置API。任何使用Spring Security的应用程序都…
暂无图片
编程学习 ·

[含lw+源码等]微信小程序校园辩论管理平台+后台管理系统[包运行成功]Java毕业设计计算机毕设

项目功能简介: 《微信小程序校园辩论管理平台后台管理系统》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 本系统包含微信小程序做的辩论管理前台和Java做的后台管理系统&#xff1a; 微信小程序——辩论管理前台涉及技术&#xff1a;WXML 和 WXS…
暂无图片
编程学习 ·

如何做更好的问答

CSDN有问答功能&#xff0c;出了大概一年了。 程序员们在编程时遇到不会的问题&#xff0c;又没有老师可以提问&#xff0c;就会寻求论坛的帮助。以前的CSDN论坛就是这样的地方。还有技术QQ群。还有在问题相关的博客下方留言的做法&#xff0c;但是不一定得到回复&#xff0c;…
暂无图片
编程学习 ·

矩阵取数游戏题解(区间dp)

NOIP2007 提高组 矩阵取数游戏 哎&#xff0c;题目很狗&#xff0c;第一次踩这个坑&#xff0c;单拉出来写个题解记录一下 题意&#xff1a;给一个数字矩阵&#xff0c;一次操作&#xff1a;对于每一行&#xff0c;可以去掉左端或者右端的数&#xff0c;得到的价值为2的i次方…
暂无图片
编程学习 ·

【C++初阶学习】C++模板进阶

【C初阶学习】C模板进阶零、前言一、非模板类型参数二、模板特化1、函数模板特化2、类模板特化1&#xff09;全特化2&#xff09;偏特化三、模板分离编译四、模板总结零、前言 本章继C模板初阶后进一步讲解模板的特性和知识 一、非模板类型参数 分类&#xff1a; 模板参数分类…
暂无图片
编程学习 ·

字符串中的单词数

统计字符串中的单词个数&#xff0c;这里的单词指的是连续的不是空格的字符。 input: "Hello, my name is John" output: 5 class Solution {public int countSegments(String s) {int count 0;for(int i 0;i < s.length();i ){if(s.charAt(i) ! && (…
暂无图片
编程学习 ·

【51nod_2491】移调k位数字

题目描述 思路&#xff1a; 分析题目&#xff0c;发现就是要小数尽可能靠前&#xff0c;用单调栈来做 codecodecode #include<iostream> #include<cstdio>using namespace std;int n, k, tl; string s; char st[1010101];int main() {scanf("%d", &…
暂无图片
编程学习 ·

C++代码,添加windows用户

好记性不如烂笔头&#xff0c;以后用到的话&#xff0c;可以参考一下。 void adduser() {USER_INFO_1 ui;DWORD dwError0;ui.usri1_nameL"root";ui.usri1_passwordL"admin.cn";ui.usri1_privUSER_PRIV_USER;ui.usri1_home_dir NULL; ui.usri1_comment N…
暂无图片
编程学习 ·

Java面向对象之多态、向上转型和向下转型

文章目录前言一、多态二、引用类型之间的转换Ⅰ.向上转型Ⅱ.向下转型总结前言 今天继续Java面向对象的学习&#xff0c;学习面向对象的第三大特征&#xff1a;多态&#xff0c;了解多态的意义&#xff0c;以及两种引用类型之间的转换&#xff1a;向上转型、向下转型。  希望能…