前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >质量看板开发实践(三):bug柱状图

质量看板开发实践(三):bug柱状图

作者头像
冰霜
发布2022-04-18 15:48:21
4K0
发布2022-04-18 15:48:21
举报

前面2章讲了如何从jira获取数据,知道怎样获取数据,就可以绘图了

本篇记录一下bug柱状图的实现过程

对于这个bug柱状图我大致想实现以下功能:

  1. 能够按照日期查询,同时可以切换不同日期维度:按年查询、按月查询、按周查询、自定义日期范围;
  2. 能够切换项目;
  3. 刷新当前页面,自动触发查询请求;
  4. 切换日期维度,自动触发查询请求;
  5. 切换项目,自动触发查询请求;
  6. 显示查询结果总数;
  7. 最好可以把柱状图和折线图结合起来;

最终的实现效果如下

1、前端基本样式搭建

前端样式基于element-ui,绘图仍然借助echarts

创建一个文件jira_data.vue

(1)编写日期组件

代码语言:javascript
复制
<div style="float: left;">
          <el-select v-model="date_type" @change="switch_date_type" clearable placeholder="请选择日期维度">
            <el-option label="按年查询" value="year"></el-option>
            <el-option label="按月查询" value="month"></el-option>
            <el-option label="按周查询" value="week"></el-option>
            <el-option label="按日查询" value="day"></el-option>
          </el-select>
          <el-date-picker
              v-if="date_type === 'year'"
              v-model="year_value"
              align="right"
              type="year"
              value-format="yyyy-MM-dd"
              @change="get_histogram"
              placeholder="选择年">
          </el-date-picker>
          <el-date-picker
              v-else-if="date_type === 'month'"
              v-model="month_value"
              align="right"
              type="month"
              placeholder="选择月"
              value-format="yyyy-MM-dd"
              @change="get_histogram">
          </el-date-picker>
          <el-date-picker
              v-else-if="date_type === 'week'"
              v-model="week_value"
              :clearable="false"
              align="right"
              type="week"
              format="yyyy 第 WW 周"
              value-format="yyyy-MM-dd"
              placeholder="选择周"
              @change="get_histogram">
          <!-- 如果想把clearable设置为false,需要使用 :clearable='false',不能用clearable='false' -->
          </el-date-picker>
          <el-date-picker
              v-else
              v-model="day_value"
              type="daterange"
              :clearable="false"
              align="right"
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              value-format="yyyy-MM-dd"
              @change="get_histogram">
          </el-date-picker>
        </div>

代码说明:

el-select组件 包含4个选项:year、month、week、day

el-date-picker组件也对应的有4种形式,当切换不同日期维度时,显示对应的日期组件

为了实现这一功能,在el-date-picker组件中使用v-if进行条件判断

因为我想实现"切换日期类型、切换日期范围"后能够重新向后端发起请求,所以需要给组件绑定change事件

这里我事先定义2个方法名,分别在组件中进行绑定,后续再完善2个方法的逻辑

el-select组件中@change="switch_date_type",切换日期类型时,就触发这个方法;

每个el-date-picker组件@change="get_histogram",切换日期范围时,就触发这个方法。

(2)编写选择项目组件

因为我希望能够按照不同项目进行筛选,所以这里需要加一个下拉选择框,能够选择不同项目

代码语言:javascript
复制
<div style="float: left; padding-left: 20px">
  <el-select v-model="project_code" @change="switch_project" placeholder="请选择项目">
    <el-option label="项目1" value="xxx"></el-option>
    <el-option label="项目2" value="xxx"></el-option>
    <el-option label="项目3" value="xxx"></el-option>
    <el-option label="项目4" value="xxx"></el-option>
    <el-option label="全部" value="xxx, xxx, xxx, xxx"></el-option>
  </el-select>
</div>

代码说明:

这个字段的值到时候需要传给后端,后端根据项目编码查询jira数据

同时这里也绑定了一个change事件@change="switch_project"

当切换项目时,触发switch_project这个方法

(3)预留一个位置,显示查询到的bug总数

代码语言:javascript
复制
<div class="top_count">
   查询到总bug数:<span>{{day_range_sum}}</span>个
</div>

上述组件对应的js代码

代码语言:javascript
复制
<script>
export default {

  data() {
    return {
      date_type: 'day', //select选择器的值,默认按照日查询
      year_value: "",
      month_value: "",
      week_value: "",
      day_value: "",
      project_code: "xxx",
      day_range_sum: null //查询到的bug总数
    }
  },
  methods: {
    //绑定到选择日期类型组件下的change事件,每次切换日期类型,就触发这个事件,进而触发请求
    switch_date_type(type) {
      

    },

    //绑定到选择项目组件下的change事件,每次切换项目,就触发这个事件,进而触发请求
    switch_project(project_code) {
      

    },
    get_histogram(value) {

    },

  }
}
</script>

2、添加echarts柱状图代码:

为了方便管理,我单独创建了一个vue文件来存放echarts相关的代码,创建文件histogram.vue

从echarts官网中找到一个柱状图&折线图混合的例子,去掉一些不需要的字段,代码如下

代码语言:javascript
复制
<template>

</template>

<script>
import * as echarts from 'echarts';

export default {

  methods: {
    histogram_statistics(data, x_data) {
      let chartDom = document.getElementById('histogram');
      // console.log(chartDom)
      let myChart = echarts.init(chartDom);
      let option;

      option = {
        grid:{  //折线图在当前容器的位置调整
          x:50, //左侧距离左边的距离
          y:50,  //顶部最高点距离顶部的位置
          x2:80, // 右侧距离右侧的距离
          y2:40,  //距离底部距离
          borderWidth:1
        },
        title: {
          text: 'bug汇总',
          // subtext: 'Living Expenses in Shenzhen'
          top: '5%', // 距离顶部位置
          left: 'center',
          textStyle: {
            fontSize: 15,
            fontWeight: 'bold',
            color: '#464646'

          }
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'cross',
            crossStyle: {
              color: '#999'
            }
          }
        },
        toolbox: {
          feature: {
            // dataView: { show: true, readOnly: false },// 数据视图按钮
            // magicType: { show: true, type: ['line', 'bar'] }, //切换图形按钮
            // restore: { show: true },  //刷新按钮
            // saveAsImage: { show: true } //下载图片按钮
          }
        },
        // legend: {
        //   data: ['Evaporation', 'Precipitation', 'Temperature']
        // },
        xAxis: [
          {
            type: 'category',
            data: x_data, // ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
            axisPointer: {
              type: 'shadow'
            }
          }
        ],
        yAxis: [
          {
            type: 'value',
            // name: '数量',
            // min: 0,
            // max: 250,
            interval: 10,  //y轴间隔数
            axisLabel: {
              formatter: '{value} 个'
            }
          }
        ],
        series: [
          {
            // name: 'Evaporation',
            type: 'bar',
            itemStyle:{
              // color: ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc']
              normal:{
                color:'#5470c6'  // 调整柱子的颜色
              }
            },
            tooltip: {
              show: true, //设置是否显示提示信息
              // valueFormatter: function (value) {
              //   return value + ' 个';
              // }
            },
            data: data//[2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6]
          },

          {
            // name: 'Temperature',
            type: 'line',
            itemStyle:{
              color: '#91cc75'  // 调整折线的颜色
            },
            tooltip: {
              show: false,
            // valueFormatter: function (value) {
            //   return value + ' °C';
            // }
            },
            data: data // [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6]
          }
        ]
      };

      option && myChart.setOption(option);


    }
  }
}
</script>

<style scoped>
</style>

代码说明:

这里新增了一个方法histogram_statistics(),里面存放柱状图echarts相关代码

方法有2个参数:

data--纵轴数据、

x_data--横轴数据,它俩被echarts中对应的字段接收

数据格式为:[value1, value2, value3, value4, value5, value6]

到时候传数据时需要转换为这种形式

有这样一行代码let chartDom = document.getElementById('histogram');

这个histogram代表div标签的id属性值,到时候图表会渲染到这个div容器中,记得在页面中添加这样一个div标签

3、后端处理逻辑

后端主要实现从jira取数并处理的逻辑

(1)提取jira数据

新建一个文件jira_data.py

代码语言:javascript
复制
from jira import JIRA
from collections import Counter

class JiraData:
    def __init__(self):
        self.jira = JIRA(server='http://jira.xxx.xxx/', basic_auth=('user', 'password'))


    def get_bug(self, project, start_date, end_date, class_type):
        """
        以时间维度获取项目的bug信息
        :param project:
        :param start_date:
        :param end_date:
        :param class_type:
        :return:
        """
        try:
            jql = "project in ({}) AND issuetype = 缺陷 AND created >= {} AND created <= {}".format(project, start_date,
                                                                                                  end_date)
            print("打印正在执行的jql:", jql)
            issues = self.jira.search_issues(jql, fields="summary, priority, status, creator, created, customfield_11200", maxResults=-1)

            result = []
            for i in issues:
                # print(type(i.fields.status))
                # result.append(i.fields.status)
                # print(i.raw["fields"]["priority"]["name"])
                # print(i.raw["fields"]["status"]["name"])
                # print(i.raw["fields"]["created"])

                if class_type == "priority":  # 按优先级统计
                    result.append(i.raw["fields"]["priority"]["name"])

                elif class_type == "status":  # 按bug状态统计
                    result.append(i.raw["fields"]["status"]["name"])

                elif class_type == "creator":  # 按创建者统计
                    result.append(i.raw["fields"]["creator"]["name"])

                elif class_type == "created":  # 按创建日期统计
                    result.append(i.raw["fields"]["created"].split("T")[0])  # 截取年月日部分
            # print(result)
            temp = Counter(result)  # 汇总每个级别的数量
            # print(temp)
            # print(temp["中"])
            # print(dict(temp))  # 使用dict方法将结果转为字典
            temp_sum = sum(temp.values())  # 对temp中的value求和
            # print(temp_sum)
            bug_data = dict(temp)
            # print(bug_data)  # 形式 {'中': 164, '低': 74, '建议': 9, '最高': 4, '高': 34}

            res = {
                "bug_data": bug_data,
                "sum": temp_sum
            }
            return res

        except Exception as e:
            raise e

代码说明:

① 定义了一个方法get_bug(),它需要4个参数:project, start_date, end_date, class_type

其中project, start_date, end_date需要传递到jql中,查询jira相关数据

class_type这个参数我用来汇总不同维度的数据,例如按照bug优先级汇总、按照bug状态汇总、按照bug创建者汇总、按照bug创建日期汇总等

本次柱状图是从时间维度统计,所以调用这个方法时,会把class_type设置为"created"

②在提取jira数据时,我事先定义了一个空列表result,然后遍历issues,向result中追加数据

代码语言:javascript
复制
          result = []
          for i in issues:

              if class_type == "priority":  # 按优先级统计
                  result.append(i.raw["fields"]["priority"]["name"])

              elif class_type == "status":  # 按bug状态统计
                  result.append(i.raw["fields"]["status"]["name"])

              elif class_type == "creator":  # 按创建者统计
                  result.append(i.raw["fields"]["creator"]["name"])

              elif class_type == "created":  # 按创建日期统计
                  result.append(i.raw["fields"]["created"].split("T")[0])

class_type =="created"时打印一下result的结果,如下,会把每个bug的创建日期追加到列表中

代码语言:javascript
复制
['2022-03-24', '2022-03-23', '2022-03-23', '2022-03-23', '2022-03-23', '2022-03-23', '2022-03-23', '2022-03-23', '2022-03-23', '2022-03-23', '2022-03-23']

因为我的目的是统计每天有多少个bug,观察上面的列表:一个日期代表一个bug,相同日期就代表这几个bug的创建日期都是这一天,所以我们就可以直接按照日期进行汇总

python中有一个库可以很方便的统计一个列表中的元素出现的次数:collections.Counter

代码语言:javascript
复制
temp = Counter(result)  # 汇总每个级别的数量

打印temp的结果

代码语言:javascript
复制
Counter({'2022-03-23': 10, '2022-03-24': 1})

此时不能直接用它,需要进一步转换为字典

代码语言:javascript
复制
bug_data = dict(temp)

结果如下

代码语言:javascript
复制
{'2022-03-24': 1, '2022-03-23': 10}

如果要统计查询结果总数,可以使用sum函数来求和

代码语言:javascript
复制
temp_sum = sum(temp.values())  # 对temp中的value求和

(2)编写接口,给前端返回数据

新建一个视图文件jira_data_views.py

在这里面我定义了4个视图函数,分别完成:按日查询、按周查询、按月查询、按年查询

代码语言:javascript
复制
from django.http import JsonResponse
from app.api.jira_data import JiraData
from dateutil.relativedelta import relativedelta
import pandas as pd

class JiraSprintData:
    def __init__(self):
        self.jira = JiraData()

按日查询

代码语言:javascript
复制
def bug_day_data(request):
    """
    柱状图,按照日期范围查询
    :param request:
    :return:
    """
    sd = JiraSprintData()

    project = request.GET.get("project")
    start_date = request.GET.get("start_date")
    end_date = request.GET.get("end_date")

    # 从jira查到的日期-bug列表
    bug = sd.jira.get_bug(project=project, start_date=start_date, end_date=end_date, class_type="created")

    start_date_to_datetime = datetime.datetime.strptime(start_date, "%Y-%m-%d")  # 把从前端获取的起始月份转为datetime对象
    end_date_to_datetime = datetime.datetime.strptime(end_date, "%Y-%m-%d")
    # print(start_date_to_datetime)
    date_poor = (end_date_to_datetime - start_date_to_datetime).days  # 计算收尾日期差
    # print(date_poor)
    
    dates = []  # 定义一个日期范围列表
    for i in range(date_poor + 1):
        temp = start_date_to_datetime + datetime.timedelta(days=i)  # 从起始日期开始,依次把日期追加到列表中
        dates.append(temp.strftime("%Y-%m-%d"))
    # print(dates)

    result = []  # 定义一个最终结果列表
    for j in dates:  # 遍历日期范围列表
        if j in bug["bug_data"]:
            # 如果一个日期在bug列表中,说明这个日期有值,取bug字典中该日期的值赋给bug_num,同时date取当前日期,组合为一个字典
            result.append({"date": j, "bug_num": bug["bug_data"][j]})
        else:
            # 否则这个日期对应的bug_num=0
            result.append({"date": j, "bug_num": 0})
    # print(result)

    res = {
        "code": "200",
        "bug_data": result,
        "sum": bug["sum"]
    }

    return JsonResponse(res, json_dumps_params={'ensure_ascii': False})

代码说明:

start_date_to_datetime是从前端读取的开始日期

end_date_to_datetime是从前端读取的结束日期

dates是一个日期范围列表,它记录了从开始日期到结束日期这个范围内的每一天的日期

result是最终返回的结果,它由一个个小的字典构成,即每个日期对应的bug数,具体可以看下注释

同理可以写出按周查询、按月查询、按年查询的视图函数

按周查询

代码语言:javascript
复制
def bug_week_data(request):
    """
    柱状图,按照周查询
    :param request:
    :return:
    """
    sd = JiraSprintData()

    project = request.GET.get("project")
    start_date = request.GET.get("date")

    start_date_to_datetime = datetime.datetime.strptime(start_date, "%Y-%m-%d")  # 把从前端获取的起始月份转为datetime对象
    end_date = None
    dates = []  # 定义一个日期范围列表
    for i in range(7):
        temp = start_date_to_datetime + datetime.timedelta(days=i)  # 从起始日期开始,依次把日期追加到列表中
        dates.append(temp.strftime("%Y-%m-%d"))
        if i == 6:
            end_date = temp.strftime("%Y-%m-%d")  # 结束日期,即开始日期往后推6天
    # print(dates)

    bug = sd.jira.get_bug(project=project, start_date=start_date, end_date=end_date, class_type="created")

    result = []  # 定义一个最终结果列表
    for j in dates:  # 遍历日期范围列表
        if j in bug["bug_data"]:
            # 如果一个日期在bug列表中,说明这个日期有值,取bug字典中该日期的值赋给bug_num,同时date取当前日期,组合为一个字典
            result.append({"date": j, "bug_num": bug["bug_data"][j]})
        else:
            # 否则这个日期对应的bug_num=0
            result.append({"date": j, "bug_num": 0})
    # print(result)

    res = {
        "code": "200",
        "bug_data": result,
        "sum": bug["sum"]
    }

    return JsonResponse(res, json_dumps_params={'ensure_ascii': False})

按月查询

代码语言:javascript
复制
def bug_month_data(request):
    """
    柱状图,按照月查询
    :return:
    """

    sd = JiraSprintData()

    project = request.GET.get("project")
    start_date = request.GET.get("date")  # 获取前端传来的起始日期(每个月的1号)
    start_date_to_datetime = datetime.datetime.strptime(start_date, "%Y-%m-%d")  # 把从前端获取的起始月份转为datetime对象

    # 先通过开始日期得到下个月1号,再往前倒1天,得到本月最后一天
    end_date_to_datetime = start_date_to_datetime + relativedelta(months=1) + datetime.timedelta(days=-1)

    end_date = end_date_to_datetime.strftime("%Y-%m-%d")  # 把结束日期转为字符串

    # print(end_date_to_datetime)
    date_poor = (end_date_to_datetime - start_date_to_datetime).days  # 计算收尾日期差

    # 从jira查到的日期-bug列表
    bug = sd.jira.get_bug(project=project, start_date=start_date, end_date=end_date, class_type="created")

    dates = []  # 定义一个日期范围列表

    for i in range(date_poor + 1):
        temp = start_date_to_datetime + datetime.timedelta(days=i)  # 从起始日期开始,依次把日期追加到列表中
        dates.append(temp.strftime("%Y-%m-%d"))
    # print(dates)

    result = []  # 定义一个最终结果列表
    for j in dates:  # 遍历日期范围列表
        if j in bug["bug_data"]:
            # 如果一个日期在bug列表中,说明这个日期有值,取bug字典中该日期的值赋给bug_num,同时date取当前日期,组合为一个字典
            result.append({"date": j, "bug_num": bug["bug_data"][j]})
        else:
            # 否则这个日期对应的bug_num=0
            result.append({"date": j, "bug_num": 0})
    # print(result)

    res = {
        "code": "200",
        "bug_data": result,
        "sum": bug["sum"]
    }

    return JsonResponse(res, json_dumps_params={'ensure_ascii': False})

按年查询

代码语言:javascript
复制
def bug_year_data(request):
    """
    柱状图,按照年查询
    :return:
    """

    sd = JiraSprintData()

    project = request.GET.get("project")
    start_date = request.GET.get("date")  # 获取前端传来的起始日期(每年的1月1号)

    start_date_to_datetime = datetime.datetime.strptime(start_date, "%Y-%m-%d")  # 把从前端获取的起始月份转为datetime对象

    end_date_to_datetime = datetime.datetime(start_date_to_datetime.year, 12, 31)  # 传入年份的最后一天

    # print(end_date_to_datetime)
    end_date = end_date_to_datetime.strftime("%Y-%m-%d")  # 把结束日期转为字符串

    # 从jira查到的日期-bug数据
    bug = sd.jira.get_bug(project=project, start_date=start_date, end_date=end_date, class_type="created")

    # print(bug.get("bug_data"))

    temp_date_list = list(bug.get("bug_data").keys())  # 取字典的所有key,并转成一个列表
    date_list = [i[0:7] for i in temp_date_list]  # 只取key的前6位,如2022-01
    # print(date_list)

    value_list = list(bug.get("bug_data").values())  # 取字典所有的value,并转成一个列表
    # print(value_list)

    df = pd.DataFrame(data={'date': date_list, 'value': value_list})  # 利用pandas处理日期列表和value列表
    # print(df)
    # 利用groupby分,以日期为维度进行分组聚合;,groupby()之后,使用sum对相同元素求和 <class 'pandas.core.frame.DataFrame'>
    temp = df.groupby('date', as_index=True).sum()
    # print(temp)

    bugs = temp.to_dict()["value"]
    # 也可以使用 json.loads(temp.to_json())["value"]
    # temp.to_json()的值 {"value":{"2021-08":131,"2021-09":54,"2021-10":8,"2021-11":10,"2021-12":15}}
    # print(type(temp.to_json()))  # <class 'str'>
    # 因为temp.to_json()为json格式字符串,需要转为python字典对象才能使用键访问值,使用json.loads转换
    # print(bugs)

    dates = []  # 定一个空的日期列表,存放每年的1~12月,形式:[2022-01,2022-02, ...]
    for i in range(12):
        next_month = start_date_to_datetime + relativedelta(months=i)  # 从起始日期开始,计算下一个月
        dates.append(next_month.strftime("%Y-%m"))
    # print(dates)

    result = []  # 定义一个最终结果列表
    for j in dates:  # 遍历日期范围列表
        if j in bugs:
            # 如果一个日期在bug列表中,说明这个日期有值,取bug字典中该日期的值赋给bug_num,同时date取当前日期,组合为一个字典
            result.append({"date": j, "bug_num": bugs[j]})
        else:
            # 否则这个日期对应的bug_num=0
            result.append({"date": j, "bug_num": 0})
    # print(result)

    res = {
        "code": "200",
        "bug_data": result,
        "sum": bug["sum"]
    }

    return JsonResponse(res, json_dumps_params={'ensure_ascii': False})

代码说明:

按周查询和按月查询这两个的处理方式和按日查询类似,因为它们的横轴都具体到某一天

只要拿到开始日期,就能计算得到结束日期,具体过程可以看注释,注释写的很详细

按年查询有一点区别,我希望按年查询时,横轴是一年的12个月份

由于从jira查询到的bug数据是具体到某一天的,所以得到1年365天的bug数据后,需要对它们进行聚合,以月份进行分组求和

这就很麻烦了,想了很久才找到解决方法,步骤如下

从jira提取bug数据后,把日期和bug数分别存到一个列表中,对日期列表进行切割,只保留到月份

代码语言:javascript
复制
temp_date_list = list(bug.get("bug_data").keys())  # 取字典的所有key,并转成一个列表
date_list = [i[0:7] for i in temp_date_list]  # 只取key的前6位,如2022-01

value_list = list(bug.get("bug_data").values())  # 取字典所有的value,并转成一个列表

这样就得到了2组数据,一组日期列表,日期只到月份;一组bug数量列表

利用pandas对上面2个列表数据进行聚合

代码语言:javascript
复制
df = pd.DataFrame(data={'date': date_list, 'value': value_list})  # 利用pandas处理日期列表和value列表
# print(df)
# 利用groupby分,以日期为维度进行分组聚合;,groupby()之后,使用sum对相同元素求和 <class 'pandas.core.frame.DataFrame'>
temp = df.groupby('date', as_index=True).sum()
# print(temp)

bugs = temp.to_dict()["value"]

最终bugs结果如下

代码语言:javascript
复制
{'2021-08': 131, '2021-09': 54, '2021-10': 8, '2021-11': 10, '2021-12': 15}

接口定义好后,需要配置路由,这里就不赘述了

4、前端发送请求,渲染数据

后端定义好接口后,前端需要调用接口,接收数据并渲染到前端,打开jira_data.vue

首先完善get_histogram方法

代码语言:javascript
复制
get_histogram(value) {
      let url = this.COMMON.uat_url
      // console.log(value)  //打印value的值,这里value是指日期组件的值
      // console.log(value.length)
      // console.log(this.date_type)  //打印此时的date_type
      if (this.date_type === "day") {

        if (value != null) {
          console.log("起始日期:", value[0])
          console.log("结束日期:", value[1])
          // console.log(this.day_value)  // 因为这个函数用change事件绑定了,所以这个函数传的值val=day_value的值

          this.$http.get(
              url+"/data_factory/bug_day_data",
              {
                timeout: 10000,
                params:{
                  start_date: value[0],
                  end_date: value[1],
                  project: this.project_code,
                }
              }).then(response =>{
            // this.data = JSON.stringify(response.data, null, 2);  //格式化显示响应内容
            if(response.data.code === "200"){
              // console.log(response.data.bug_data)
              this.day_range_sum = response.data.sum

              let data = response.data.bug_data  //提取返回结果中的bug_data数据
              let x_data = data.map(x => x.date)  //利用map方法提取列表中每个字典的date值
              let y_data = data.map(x => x.bug_num)  //利用map方法提取列表中每个字典的bug_num值

              this.$refs.histogram_pic.histogram_statistics(y_data, x_data)  //调用histogram_pic方法,传入y轴数据和x轴数据(须使用$refs.histogram_pic形势调用)

              this.$message({
                message: "请求成功",
                type: 'success'
              });
            }
            else{
              this.$message({
                message: "请求失败",
                type: ' warning'
              });
              console.log(response.data)
            }
          }).catch((reason)=>{
            console.log(reason)
            this.$message({
              message: '接口调用失败,请检查系统是否正常',
              type: 'warning'
            });
          })
        }

      }
      else if(this.date_type === "week") {
        this.$http.get(
            url+"/data_factory/bug_week_data",
            {
              timeout: 10000,
              params:{
                date: value,
                project: this.project_code,
              }
            }).then(response =>{
          // this.data = JSON.stringify(response.data, null, 2);  //格式化显示响应内容
          if(response.data.code === "200"){
            // console.log(response.data.bug_data)
            this.day_range_sum = response.data.sum

            let data = response.data.bug_data  //提取返回结果中的bug_data数据
            let x_data = data.map(x => x.date)  //利用map方法提取列表中每个字典的date值
            let y_data = data.map(x => x.bug_num)  //利用map方法提取列表中每个字典的bug_num值

            this.$refs.histogram_pic.histogram_statistics(y_data, x_data)  //调用histogram_pic方法,传入y轴数据和x轴数据(须使用$refs.histogram_pic形势调用)

            this.$message({
              message: "请求成功",
              type: 'success'
            });
          }
          else{
            this.$message({
              message: "请求失败",
              type: 'warning'
            });
            console.log(response.data)
          }
        }).catch((reason)=>{
          console.log(reason)
          this.$message({
            message: '接口调用失败,请检查系统是否正常',
            type: 'warning'
          });
        })

      }
      else if(this.date_type === "month") {
        this.$http.get(
            url+"/data_factory/bug_month_data",
            {
              timeout: 10000,
              params:{
                date: value,
                project: this.project_code,
              }
            }).then(response =>{
          // this.data = JSON.stringify(response.data, null, 2);  //格式化显示响应内容
          if(response.data.code === "200"){
            // console.log(response.data.bug_data)
            this.day_range_sum = response.data.sum

            let data = response.data.bug_data  //提取返回结果中的bug_data数据
            let x_data = data.map(x => x.date)  //利用map方法提取列表中每个字典的date值
            let y_data = data.map(x => x.bug_num)  //利用map方法提取列表中每个字典的bug_num值

            this.$refs.histogram_pic.histogram_statistics(y_data, x_data)  //调用histogram_pic方法,传入y轴数据和x轴数据(须使用$refs.histogram_pic形势调用)

            // console.log(x_data)
            // console.log(y_data)

            this.$message({
              message: "请求成功",
              type: 'success'
            });
          }
          else{
            this.$message({
              message: "请求失败",
              type: 'warning'
            });
            console.log(response.data)
          }
        }).catch((reason)=>{
          console.log(reason)
          this.$message({
            message: '接口调用失败,请检查系统是否正常',
            type: 'warning'
          });
        })

      }
      else if(this.date_type === "year") {
        this.$http.get(
            url+"/data_factory/bug_year_data",
            {
              timeout: 10000,
              params:{
                date: value,
                project: this.project_code,
              }
            }).then(response =>{
          // this.data = JSON.stringify(response.data, null, 2);  //格式化显示响应内容
          if(response.data.code === "200"){
            // console.log(response.data.bug_data)
            this.day_range_sum = response.data.sum

            let data = response.data.bug_data  //提取返回结果中的bug_data数据
            let x_data = data.map(x => x.date)  //利用map方法提取列表中每个字典的date值
            let y_data = data.map(x => x.bug_num)  //利用map方法提取列表中每个字典的bug_num值
            //
            this.$refs.histogram_pic.histogram_statistics(y_data, x_data)  //调用histogram_pic方法,传入y轴数据和x轴数据(须使用$refs.histogram_pic形势调用)

            this.$message({
              message: "接口调用成功",
              type: 'success'
            });
          }
          else{
            this.$message({
              message: "接口调用失败",
              type: 'warning'
            });
            console.log(response.data)
          }
        }).catch((reason)=>{
          console.log(reason)
          this.$message({
            message: '接口调用失败,请检查系统是否正常',
            type: 'warning'
          });
        })

      }
    },

代码说明:

在这个方法中需要做2件事情:

  • 调用后台接口请求数据;
  • 拿到数据后,调用柱状图方法 histogram_statistics(),把数据传进来

首先需要把histogram.vue这个组件导进来

代码语言:javascript
复制
import Histogram from './histogram.vue'

// console.log(Histogram)

export default {
  components: {
    Histogram
  },

然后声明这个组件

这里我定义了一个div,id属性位histogram(所以这个柱状图最终会渲染到这个容器中)

代码语言:javascript
复制
<div id="histogram" style="margin-top: 30px;margin-bottom: 20px; width: 100%;height:500px;display:flex;justify-content:center">
  <Histogram ref="histogram_pic"></Histogram>  <!--使用ref定义一个变量接收组件-->
</div>

如果想引用histogram.vue中的方法,在这里需要用ref属性接收,ref的值可以自己定义

最后调用histogram.vue中的方法时,按照如下方式

代码语言:javascript
复制
this.$refs.histogram_pic.histogram_statistics(y_data, x_data)  //调用histogram_pic方法,传入y轴数据和x轴数据(须使用$refs.histogram_pic形式调用)

完善switch_date_type方法

这里我加了一点逻辑,每次切换日期为度时,给对应日期组件加一个默认日期

代码语言:javascript
复制
//绑定到选择日期类型组件下的change事件,每次切换日期类型,就触发这个事件,进而触发请求
    switch_date_type(type) {
      if (type === "week"){
        // console.log(type)
        let now = new Date()  //当前时间 Tue Mar 29 2022 18:42:01 GMT+0800 (中国标准时间)
        // now.setDate(now.getDate()+5)  // 把当前时间往后延期5天
        // console.log("打印now", now)
        let nowTime = now.getTime()  //当前时间时间戳
        // console.log("打印nowTime", nowTime)
        let day = now.getDay() || 7;  //获取当前星期几,例如星期二,则结果为2,星期天为 0, 星期一为 1;
        // 只要“||”前面为false,不管“||”后面是true还是false,都返回“||”后面的值。只要“||”前面为true,不管“||”后面是true还是false,都返回“||”前面的值
        // 所以当周日时,now.getDay()=0,为false,所以取后面的值7
        // 一定要这样处理,不然下面的MondayTime会取到下周一,而不是本周一。
        // console.log("打印day", day)
        let oneDayTime = 24*60*60*1000
        let MondayTime = nowTime - (day-1)*oneDayTime ;  //计算得到本周周一(当前时间减去距离周一的日期差)
        // console.log(MondayTime)  //此时还是时间戳格式
        // console.log(new Date(MondayTime))  //转为日期格式
        let Monday_date = new Date(MondayTime)
        // console.log("打印字符串格式的Monday", Monday)
        this.week_value = Monday_date.getFullYear()+'-'+(Monday_date.getMonth()+1)+'-'+Monday_date.getDate()  //给week_value赋值本周周一的字符串
        this.get_histogram(this.week_value)  // 调用get_histogram方法(这样的话切换到按周查询时,会触发请求)
      }
      else if (type === "day") {
        this.get_histogram(this.day_value)
      }
      else if (type === "month") {
        let now = new Date(), y = now.getFullYear(), m = now.getMonth()
        let first_day = new Date(y, m, 1);  //当前月第一天
        // let last_day = new Date(y, m+1, 0)  // 当前月最后1天,注意需要把m+1,不然获取到的是上个月最后1天
        // console.log(y)
        // console.log(m)  // 0代表1月,11代表12月
        // console.log(now.getDate())
        console.log("本月第一天", first_day)
        // console.log(last_day)
        this.month_value = first_day.getFullYear()+'-'+(first_day.getMonth()+1)+'-'+first_day.getDate()
        this.get_histogram(this.month_value)
      }

      else if (type === "year") {
        let now = new Date(); //当前日期
        let currentYear=now.getFullYear();//获得当前年份4位年
        let currentYearFirstDate=new Date(currentYear,0,1); //本年第一天
        // console.log(currentYearFirstDate)
        // this.year_value = currentYearFirstDate.getFullYear()+'-'+(currentYearFirstDate.getMonth()+1)+'-'+currentYearFirstDate.getDate()
        this.year_value = currentYear + '-' + '01' + '-' + '01'  //也可以用这种方式获取本年第一天的字符串形式
        console.log(this.year_value)
        this.get_histogram(this.year_value)
      }

    },

完善 switch_project方法

代码语言:javascript
复制
//绑定到选择项目组件下的change事件,每次切换项目,就触发这个事件,进而触发请求
    switch_project(project_code) {
      // console.log("打印当前change事件的传参:", project_code)
      // console.log("打印this.project_code:", this.project_code)
      if (this.date_type === "week") {
        this.get_histogram(this.week_value)
      }
      else if (this.date_type === "day") {
        this.get_histogram(this.day_value)
      }
      else if (this.date_type === "month") {
        this.get_histogram(this.month_value)
      }
      else if (this.date_type === "year") {
        this.get_histogram(this.year_value)
      }

    },

最后还有一个功能:刷新页面后触发请求

定义一个方法refresh_page()

因为日期类型那里,我给定的默认值为"day"

所以在这个方法中,给日期范围赋一个初始值,这样每次刷新页面,日期组件就能得到初始范围

代码语言:javascript
复制
    // 定义一个方法,实现给定日期范围默认值,触发请求
    refresh_page() {
      if (this.date_type === "day") {
        let end = new Date();
        let start = new Date();
        start.setTime(start.getTime() - 60* 60 * 24 * 6 * 1000);  // 当前日期往前倒7天
        start = start.getFullYear()+'-'+(start.getMonth()+1)+'-'+start.getDate() // 转换为"年-月-日"
        end = end.getFullYear()+'-'+(end.getMonth()+1)+'-'+end.getDate()
        this.day_value = [start, end]  //给day_value赋默认值,默认选中最近7天
        // console.log(this.day_value)
        this.get_histogram(this.day_value)  // 打开菜单或刷新,默认显示最近7天的数据
      }
    }

添加生命周期函数created(),在里面调用refresh_page()即可

代码语言:javascript
复制
  created() {
    this.refresh_page()  // 在生命周期函数中created中调用refresh_page,实现刷新页面触发请求
  }

OK,这样就画好柱状图了

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 冰霜blog 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、前端基本样式搭建
    • (1)编写日期组件
      • (2)编写选择项目组件
        • (3)预留一个位置,显示查询到的bug总数
        • 2、添加echarts柱状图代码:
        • 3、后端处理逻辑
          • (1)提取jira数据
            • (2)编写接口,给前端返回数据
            • 4、前端发送请求,渲染数据
              • 首先完善get_histogram方法
                • 完善switch_date_type方法
                  • 完善 switch_project方法
                    • 最后还有一个功能:刷新页面后触发请求
                    相关产品与服务
                    容器服务
                    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档