Browse Source

ADD:完成树状bug列表的树状图

wjj 3 years ago
parent
commit
21a38d43d8

BIN
src/pages/bugs/assets/grade.png


BIN
src/pages/bugs/assets/noGrade.png


+ 298 - 10
src/pages/bugs/components/BugTreeGraph/index.jsx

@@ -2,26 +2,314 @@ import { Col, Image, Spin } from 'antd';
 import React, { useEffect, useState } from 'react';
 import { connect } from 'umi';
 import styles from './index.less';
-import { timeToString } from '@/utils/common';
-import {
-  DislikeOutlined, LeftOutlined,
-  LikeOutlined, RightOutlined,
-} from '@ant-design/icons';
+
 import { recurrent, severity, bug_categories } from '@/pages/edit/components/Step2/const';
+import * as echarts from 'echarts';
+
+const imgArr = ['grade.png', 'noGrade.png'];
 
 const BugTreeGraph = (props) => {
-  const { dispatch,reportCommonInfo,treeGraph } = props;
+  const { dispatch, bugItemDetail, treeGraph } = props;
+
+  const [path,setPath] = useState([]);
+  const [invalid,setInvalid] = useState([]);
+  const [treeData,setTreeData] = useState([]);
+
+  //初始化echarts
+  const initEcharts = () => {
+    const item_color = 'rgba(226,245,240,1)';
+    const border_color = 'rgba(0,0,0,0.9)';
+    const categories = [
+      {
+        'name': '未评分',
+        'icon': 'image://' + require('../../assets/' + imgArr[1]),
+        'itemStyle': { 'normal': { 'color': item_color, 'borderColor': border_color } },
+      },
+      {
+        'name': '已评分',
+        'icon': 'image://' + require('../../assets/' + imgArr[0]),
+        'itemStyle': { 'normal': { 'color': item_color, 'borderColor': border_color } },
+      },
+    ];
+    let echartOption = {
+      legend: {     //配置legend,这里的data,要对应type为‘bar’的series数据项的‘name’名称,作为图例的说明
+        data: categories,
+        selectedMode: false,  //图例禁止点击
+        top: '3%',
+        left: '3%',
+        itemWidth: 15,
+        itemHeight: 15,
+        orient: 'vertical',
+      },
+      tooltip: {
+        trigger: 'item',
+        triggerOn: 'mousemove',
+        formatter: function(params) {
+          return params.name + '分数:' + params.value;
+        },
+      },
+      grid: {
+        z: 1,    //grid作为柱状图的坐标系,其层级要和仪表图层级不同,同时隐藏
+        show: false,
+        left: '-30%',
+        right: '4%',
+        bottom: '3%',
+        containLabel: true,
+        splitLine: {
+          show: false,    //隐藏分割线
+        },
+
+      },
+
+      xAxis: [   //这里有很多的show,必须都设置成不显示
+        {
+          type: 'category',
+          data: [],
+          axisLine: {
+            show: false,
+          },
+          splitLine: {
+            show: false,
+          },
+          splitArea: {
+            interval: 'auto',
+            show: false,
+          },
+        },
+      ],
+
+      yAxis: [ //这里有很多的show,必须都设置成不显示
+        {
+          type: 'value',
+          axisLine: {
+            show: false,
+          },
+          splitLine: {
+            show: false,
+          },
+        },
+      ],
+
+      toolbox: {
+        show: false,
+      },
+      series: [
+        {
+          type: 'tree',
+
+          name: 'tree1',
+
+          data: treeData,
+
+          top: '5%',
+          left: '5%',
+          bottom: '5%',
+          right: '5%',
+          orient: 'vertical',
+          symbolSize: 20,
+          label: {
+            normal: {
+              position: 'left',
+              verticalAlign: 'middle',
+              align: 'right',
+            },
+          },
+
+          leaves: {
+            label: {
+              normal: {
+                position: 'right',
+                verticalAlign: 'middle',
+                align: 'left',
+              },
+            },
+          },
+
+          expandAndCollapse: false,
+          initialTreeDepth: 10,
+          animationDuration: 550,
+          animationDurationUpdate: 750,
+        },
+        {
+          name: categories[0].name,
+          type: 'bar',
+          barWidth: '60%',  //不显示,可以随便设置
+          data: [0],
+          itemStyle: {
+            normal: {
+              color: '#41C468',  //这里的图例要注意,颜色设置和仪表盘的颜色对应起来
+            },
+          },
+        },
+        {
+          name: categories[1].name,
+          type: 'bar',
+          barWidth: '60%',
+          data: [0],
+          itemStyle: {
+            normal: {
+              color: '#70C1B3',
+            },
+          },
+        },
+      ],
+    };
+    const chart = echarts.init(document.getElementById('treeGraphChart'));
+    console.log(chart);
+    chart.setOption(echartOption);
+  };
+
+  //包装数据
+  const packageData = ()=> {
+    //统计node数量
+    // path.forEach(onePath => {
+    //   onePath.forEach(node => {
+    //     if (this.nodes.indexOf(node) === -1) {
+    //       this.nodes.push(node);
+    //     }
+    //   })
+    // })
+    //包装树状结构
+    let json1 = {};
+    path.forEach(onePath => {
+      if (!json1.hasOwnProperty('name')) {
+        json1['name'] = onePath[0];
+        json1['children'] = [];
+      }
+      let jsonTemp = pathRecursion(json1, onePath, 1);
+      if (JSON.stringify(jsonTemp) !== '{}') {
+        json1['children'].push(jsonTemp);
+      }
+    })
+    setTreeData([json1])
+    initItemRecursion(treeData);
+  }
+
+  //封装后端数据
+  const pathRecursion = (json1, onePath, i)=>{
+    let flag = false;
+    if (i === onePath.length) {
+      return {};
+    }
+
+    let children = json1.children;
+    if (children !== undefined && children.length !== 0) {
+      for (let j = 0; j < children.length; j++) {
+        if (children[j].name === onePath[i]) {
+          // var json2  = {};
+          // json2['name'] = onePath[i];
+          flag = true;
+          let jsonTemp = pathRecursion(children[j], onePath, i + 1);
+          if (JSON.stringify(jsonTemp) !== '{}') {
+            children[j].children.push(jsonTemp);
+          }
+        }
+      }
+      if (flag) {
+        return {};
+      } else {
+        let json2 = {};
+        json2['name'] = onePath[i];
+        json2['children'] = [];
+        let jsonTemp = pathRecursion(json2, onePath, i + 1);
+        if (JSON.stringify(jsonTemp) !== '{}') {
+          json2['children'].push(jsonTemp);
+        }
+        return json2;
+      }
+    }
+
+    let json2 = {};
+    json2['name'] = onePath[i];
+    json2['children'] = [];
+    let jsonTemp = pathRecursion(json2, onePath, i + 1);
+    if (JSON.stringify(jsonTemp) !== '{}') {
+      json2['children'].push(jsonTemp);
+    }
+    return json2;
+  }
+
+  //初次迭代遍历
+  const initItemRecursion = (items) => {
+    console.log('初次遍历')
+    //按理说是初次遍历结束了才会initcharts
+    if (items !== undefined) {
+      items.forEach(item => {
+        let temp = item.name;
+        item['value'] = 0;
+        item['id'] = temp;
+        item['symbol'] = 'emptyCircle';
+        item['category'] = 0;
+        item['name'] = transformName(temp);
+        // this.scores.forEach(bugScore => {
+        //   if (bugScore[0] == item.id) {
+        //     item['symbol'] = 'circle';
+        //     item['value'] = Number(bugScore[1]);
+        //   }
+        // })
+        if (item.children) {
+          initItemRecursion(item.children);
+        }
+      });
+    }
+  }
+
+  //辅助类函数
+  const transformName = (str)=> {
+    let ret = '';
+    if (str.length > 3) {
+      ret = str.substr(str.length - 3, str.length);
+    } else {
+      ret = str;
+    }
+    return ret;
+  }
+
+  useEffect(()=>{
+    if(treeData.length){
+      initItemRecursion(treeData);
+      initEcharts();
+    }
+  },[treeData])
+
+  useEffect(()=>{
+    if(JSON.stringify(bugItemDetail)!=='{}'){
+      dispatch({
+        type:'allBugs/getTreeGraph',
+        payload:{
+          id:bugItemDetail.detail.id
+        }
+      }).then(res=>{
+        if(res){
+          setPath(res['path']);
+          setInvalid(res['invalid'])
+        }
+        // this.scores = data['score'];
+        // if (this.treeRootsExist) {
+        //   this.treeTitle = '树' + index + '图';
+        // } else {
+        //   this.treeTitle = 'Bug' + index + '图';
+        //   this.getBugDetail(this.treeRoots[index - 1][0]);
+        // }
+        // packageData();
+        // initEcharts();
+      })
+    }
+  },[bugItemDetail])
 
+  useEffect(()=>{
+    if(path.length){
+      packageData();
+    }
+  },[path])
   return (
-    // detail && detail.id ?
-    //    : <Spin />
     <div className={styles.treeGraph}>
-      graph
+      <div id="treeGraphChart" className={styles.treeGraphChart}></div>
     </div>
   );
 };
 
 export default connect(({ allBugs, editReport }) => ({
   treeGraph: allBugs.treeGraph,
-  reportCommonInfo: editReport.reportCommonInfo,
+  bugItemDetail: allBugs.bugItemDetail,
 }))(BugTreeGraph);

+ 4 - 0
src/pages/bugs/components/BugTreeGraph/index.less

@@ -1,5 +1,9 @@
 @import '~antd/es/style/themes/default.less';
 
 .treeGraph {
+  .treeGraphChart{
+    width: 100%;
+    height: 520px;
+  }
 
 }

+ 1 - 1
src/pages/bugs/model.js

@@ -50,11 +50,11 @@ const Model = {
     * getTreeGraph({ payload }, { call, put }) {
       const {id} = payload;
       let res = yield call(getTreeGraph, id);
-      console.log(res);
       yield put({
         type: 'saveTreeGraph',
         payload: res,
       });
+      return res;
     },
   },
   reducers: {

+ 0 - 3
src/pages/bugs/service.js

@@ -1,7 +1,6 @@
 import request from 'umi-request';
 
 // todo:获取bug总数,点赞、点踩总数
-// eslint-disable-next-line camelcase
 export async function getReportReview(report_id,case_take_id) {
   return request('/Bug/api/report/reportReview', {
     method: 'get',
@@ -13,7 +12,6 @@ export async function getReportReview(report_id,case_take_id) {
 }
 
 // todo:获取树状列表
-// eslint-disable-next-line camelcase
 export async function getTreeList(case_take_id,start,count,page) {
   return request('/Bug/api/history/getTreesStu', {
     method: 'get',
@@ -27,7 +25,6 @@ export async function getTreeList(case_take_id,start,count,page) {
 }
 
 // todo:获取单一状列表
-// eslint-disable-next-line camelcase
 export async function getSingleList(case_take_id,start,count,page) {
   return request('/Bug/api/history/getSingleStu', {
     method: 'get',

+ 26 - 0
src/pages/edit/components/BugGuideTree/index.jsx

@@ -411,6 +411,32 @@ const BugGuideTree = (props) => {
     setRecPageFirst();
   };
 
+  //包装数据
+  const packageData= () => {
+    //统计node数量
+    this.path.forEach(onePath => {
+      onePath.forEach(node => {
+        if (this.nodes.indexOf(node) == -1) {
+          this.nodes.push(node);
+        }
+      })
+    })
+    //包装树状结构
+    let json1 = {};
+    this.path.forEach(onePath => {
+      if (!json1.hasOwnProperty('name')) {
+        json1['name'] = onePath[0];
+        json1['children'] = [];
+      }
+      var jsonTemp = this.pathRecursion(json1, onePath, 1);
+      if (JSON.stringify(jsonTemp) != '{}') {
+        json1['children'].push(jsonTemp);
+      }
+    })
+    this.treeData = [json1];
+    this.initItemRecursion(this.treeData);
+  }
+
   useEffect(() => {
     initChartData();
     initItemRecursion(jsonPath.children);