Vue 数据统计模块(折线+饼图)

1. 数据统计的页面布局

<template>
  <div>
    <!-- 面包屑导航-->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>欢迎页</el-breadcrumb-item>
    </el-breadcrumb>

    <!-- 数据统计-->
    <el-row :gutter="10">
        <el-col :span="6">
            <div class="statistics" style="background:#409eff" >
                <div class="title">
                    <p>用户统计</p>
                    <el-tag size="mini" type="success">实时</el-tag>
                </div>
                <div class="num">7</div>
                <div class="tip">当前总用户数量</div>
            </div>
        </el-col>
        <el-col :span="6">
            <div class="statistics" style="background:#E6A23C" >
                <div class="title">
                    <p>商品统计</p>
                    <el-tag size="mini" type="info">实时</el-tag>
                </div>
                <div class="num">7</div>
                <div class="tip">当前总商品数量</div>
            </div>
        </el-col>
        <el-col :span="6">
            <div class="statistics" style="background:#67C23A" >
                <div class="title">
                    <p>订单统计</p>
                    <el-tag size="mini" type="warning">实时</el-tag>
                </div>
                <div class="num">7</div>
                <div class="tip">当前总订单数量</div>
            </div>
        </el-col>
        <el-col :span="6">
            <div class="statistics" style="background:#909399" >
                <div class="title">
                    <p>销售统计</p>
                    <el-tag size="mini" type="primary">实时</el-tag>
                </div>
                <div class="num">7</div>
                <div class="tip">当前总销售()</div>
            </div>
        </el-col>
    </el-row>
  </div>
</template>

<script>
export default {}
</script>

<style lang="less" scoped>
.el-row{
    padding: 0 9px;
    .statistics{
        color: white;
        height: 100px;
        border-radius:4px;
        padding: 0 8px;
        .title{
            display: flex; // 弹性布局
            justify-content: space-between; // 两边对齐
            align-items: center; // 垂直居中
        }
        p{
            font-size: 13px;
            font-weight: bold;
        }
        .num{
            font-size: 20px;
            font-weight: bold;
            text-align: center;
        }
        .tip{
            font-size: 12px;
        }
    }
}
</style>

2.数据统计

在这里插入图片描述

Vue 数据统计模块(折线+饼图)_第1张图片

<div class="num">{{totalUsers}}</div>
  data(){
        return{
            totalUsers:0,
        }
    },
    created(){
        this.getUserList()
    },
    methods:{
        async getUserList(){
             const {data:res} = await this.$http.get('users',{
                 params:{
                     pagenum:1,
                     pagesize:1
                 }
        })
        if(res.meta.status !== 200){
            return this.$message.error('获取用户数据失败')
        }
        this.totalUsers = res.data.total

        }
       
    }

Vue 数据统计模块(折线+饼图)_第2张图片
Vue 数据统计模块(折线+饼图)_第3张图片

async getGoodsrList(){
             const {data:res} = await this.$http.get('goods',{
                 params:{
                     pagenum:1,
                     pagesize:1
                 }
        })
        if(res.meta.status !== 200){
            return this.$message.error('获取商品数据失败')
        }
        this.totalGoods = res.data.total

        },
       
    }

Vue 数据统计模块(折线+饼图)_第4张图片

async getOrderList(){
             const {data:res} = await this.$http.get('orders')
        if(res.meta.status !== 200){
            return this.$message.error('获取订单数据失败')
        }
        this.totalOrders = res.data.total

        // 计算总销售额
        this.orderList = res.data.goods
        this.orderList.forEach(item=>{
            if(item.pay_status==='1'){
                this.totalSales+=item.order_price
            }
        })
        },

在这里插入图片描述

3.折现图展示订单趋势

这里需要用到echarts

cnpm install echarts -S 

创建显示图表的区域

<!-- Echarts图标-->
    <div class="echarts-container">
      <el-card id="chart1"></el-card>
      <el-card id="chart2"></el-card>
    </div>
  </div>
</template>

导入echarts

import echarts from 'echarts'
async getOrderList() {
      const { data: res } = await this.$http.get('orders')
      if (res.meta.status !== 200) {
        return this.$message.error('获取订单数据失败')
      }
      this.totalOrders = res.data.total
    

      // 计算总销售额
      this.orderList = res.data.goods
      this.orderList.forEach((item) => {
        if (item.pay_status === '1') {
          this.totalSales += item.order_price
        }
      })

      // 展示图表
      this.initChart1()
    },
    initChart1() {
      // 创建echarts实例  获取要展示的区域
      var chart1 = echarts.init(document.getElementById('chart1'))
      // 订单趋势
      var option = {
        title: {
          text: '订单趋势',
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'line',
          },
        },
        xAxis: {
          type: 'category',
          data: [],
        },
        yAxis: {
          type: 'value',
        },
        series: [
          {
            type: 'line',
            smooth: true,
            data: []
          },
        ],
      }
      
        // 根据时间进行排序
        this.orderList.sort(function(a,b){
            return a.create_time - b.create_time
        })
        // 时间作为key 金额作为value
        let data = []
        this.orderList.forEach(item=>{
            if(item.pay_status==="1"){
                // 将时间进行转换
                let key =  this.$utils.formatToDate(item.create_time)
                // 将同一天下的订单金额加起来
                if(!data[key]){
                    // 如果数组中没有那么直接将时间和金额对应添加进既可以
                    data[key] = item.order_price
                }else{
                    // 如果数组中已经存在该日期我们将金额累加即可(这一天订单在一单以上)
                    data[key] += item.order_price
                }  
            }
        })
        // 将数据添加到options中
        for(var key in data){
            option.xAxis.data.push(key)
            option.series[0].data.push(data[key])
        }
      chart1.setOption(option)
    },

4.饼状图展示订单状态

Vue 数据统计模块(折线+饼图)_第5张图片

 initChart2() {
      var chart2 = echarts.init(document.getElementById('chart2'))
        
      // 订单状态
      var option = {
        title: {
          text: '订单状态',
        },
        tooltip: {
          trigger: 'item',
          formatter: '{b} : {c} ({d}%)',
        },
        legend: {
          orient: 'vertical',
          left: 'right',
          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: '搜索引擎'}
            ],
            // data: [],
            emphasis: {
              itemStyle: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: 'rgba(0, 0, 0, 0.5)',
              },
            },
          },
        ],
      }

      // 对数据进行处理
      var data = [
          {
              name:'已付款',
              value:0
          },
          {
              name:'未付款',
              value:0
          }
      ]

      this.orderList.forEach(item=>{
          if(item.pay_status==='1'){
              data[0].value++
          }else{
             data[1].value++ 
          }
      })
      for(var item of data){
          option.legend.data.push(item.name)
          option.series[0].data.push(item)
      }
      chart2.setOption(option)
    },

项目细节优化

在这里插入图片描述

在登录的时候和后端交互需要一定的时间,可以用进度条动画表示
安装第三方依赖

npm install --save nprogress

main.js中全局引入
Vue 数据统计模块(折线+饼图)_第6张图片

完整代码

<template>
  <div>
    <!-- 面包屑导航-->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>欢迎页</el-breadcrumb-item>
    </el-breadcrumb>

    <!-- 数据统计-->
    <el-row :gutter="10">
      <el-col :span="6">
        <div class="statistics" style="background: #409eff">
          <div class="title">
            <p>用户统计</p>
            <el-tag size="mini" type="success">实时</el-tag>
          </div>
          <div class="num">{{ totalUsers }}</div>
          <div class="tip">当前总用户数量</div>
        </div>
      </el-col>
      <el-col :span="6">
        <div class="statistics" style="background: #e6a23c">
          <div class="title">
            <p>商品统计</p>
            <el-tag size="mini" type="info">实时</el-tag>
          </div>
          <div class="num">{{ totalGoods }}</div>
          <div class="tip">当前总商品数量</div>
        </div>
      </el-col>
      <el-col :span="6">
        <div class="statistics" style="background: #67c23a">
          <div class="title">
            <p>订单统计</p>
            <el-tag size="mini" type="warning">实时</el-tag>
          </div>
          <div class="num">{{ totalOrders }}</div>
          <div class="tip">当前总订单数量</div>
        </div>
      </el-col>
      <el-col :span="6">
        <div class="statistics" style="background: #909399">
          <div class="title">
            <p>销售统计</p>
            <el-tag size="mini" type="primary">实时</el-tag>
          </div>
          <div class="num">{{ totalSales }}</div>
          <div class="tip">当前总销售()</div>
        </div>
      </el-col>
    </el-row>

    <!-- Echarts图标-->
    <div class="echarts-container">
      <el-card id="chart1"></el-card>
      <el-card id="chart2"></el-card>
    </div>
  </div>
</template>

<script>
import echarts from 'echarts'

export default {
  data() {
    return {
      totalUsers: 0,
      totalGoods: 0,
      totalOrders: 0,
      totalSales: 0,
      // 订单数据
      orderList: [],
    }
  },
  created() {
    this.getUserList()
    this.getGoodsrList()
    this.getOrderList()
  },
  methods: {
    async getUserList() {
      const { data: res } = await this.$http.get('users', {
        params: {
          pagenum: 1,
          pagesize: 1,
        },
      })
      if (res.meta.status !== 200) {
        return this.$message.error('获取用户数据失败')
      }
      this.totalUsers = res.data.total
    },
    async getGoodsrList() {
      const { data: res } = await this.$http.get('goods', {
        params: {
          pagenum: 1,
          pagesize: 1,
        },
      })
      if (res.meta.status !== 200) {
        return this.$message.error('获取商品数据失败')
      }
      this.totalGoods = res.data.total
    },

    async getOrderList() {
      const { data: res } = await this.$http.get('orders')
      if (res.meta.status !== 200) {
        return this.$message.error('获取订单数据失败')
      }
      this.totalOrders = res.data.total

      // 计算总销售额
      this.orderList = res.data.goods
      this.orderList.forEach((item) => {
        if (item.pay_status === '1') {
          this.totalSales += item.order_price
        }
      })

      // 展示图表
      this.initChart1()
      this.initChart2()
    },
    initChart1() {
      // 创建echarts实例  获取要展示的区域
      var chart1 = echarts.init(document.getElementById('chart1'))
      // 订单趋势
      var option = {
        title: {
          text: '订单趋势',
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'line',
          },
        },
        xAxis: {
          type: 'category',
          data: [],
        },
        yAxis: {
          type: 'value',
        },
        series: [
          {
            type: 'line',
            smooth: true,
            data: [],
          },
        ],
      }

      // 根据时间进行排序
      this.orderList.sort(function (a, b) {
        return a.create_time - b.create_time
      })
      // 时间作为key 金额作为value
      let data = []
      this.orderList.forEach((item) => {
        if (item.pay_status === '1') {
          // 将时间进行转换
          let key = this.$utils.formatToDate(item.create_time)
          // 将同一天下的订单金额加起来
          if (!data[key]) {
            // 如果数组中没有那么直接将时间和金额对应添加进既可以
            data[key] = item.order_price
          } else {
            // 如果数组中已经存在该日期我们将金额累加即可(这一天订单在一单以上)
            data[key] += item.order_price
          }
        }
      })
      // 将数据添加到options中
      for (var key in data) {
        option.xAxis.data.push(key)
        option.series[0].data.push(data[key])
      }
      chart1.setOption(option)
    },
    initChart2() {
      var chart2 = echarts.init(document.getElementById('chart2'))
        
      // 订单状态
      var option = {
        title: {
          text: '订单状态',
        },
        tooltip: {
          trigger: 'item',
          formatter: '{b} : {c} ({d}%)',
        },
        legend: {
          orient: 'vertical',
          left: 'right',
          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: '搜索引擎'}
            ],
            // data: [],
            emphasis: {
              itemStyle: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: 'rgba(0, 0, 0, 0.5)',
              },
            },
          },
        ],
      }

      // 对数据进行处理
      var data = [
          {
              name:'已付款',
              value:0
          },
          {
              name:'未付款',
              value:0
          }
      ]

      this.orderList.forEach(item=>{
          if(item.pay_status==='1'){
              data[0].value++
          }else{
             data[1].value++ 
          }
      })
      for(var item of data){
          option.legend.data.push(item.name)
          option.series[0].data.push(item)
      }
      chart2.setOption(option)
    },
  },
}
</script>

<style lang="less" scoped>
.el-row {
  padding: 0 9px;
  .statistics {
    color: white;
    height: 100px;
    border-radius: 4px;
    padding: 0 8px;
    .title {
      display: flex; // 弹性布局
      justify-content: space-between; // 两边对齐
      align-items: center; // 垂直居中
    }
    p {
      font-size: 13px;
      font-weight: bold;
    }
    .num {
      font-size: 20px;
      font-weight: bold;
      text-align: center;
    }
    .tip {
      font-size: 12px;
    }
  }
}
.echarts-container {
  display: flex; // 同一行显示
  justify-content: space-between;
  margin-top: 10px;
  .el-card {
    height: 400px;
    width: 50%;
    margin: 0 8px; // 左右0 上下8
    padding: 20px; // 内边距
  }
}
</style>

你可能感兴趣的:(Vue,vue.js,分类,javascript)