echarts关系图、动态数据、根据不同状态更换不同背景图片

需求:

 1:动态生成流程图

 2:根据待办、已办(或者其他类似需求)区分不同的背景颜色

 3:鼠标划过展示相应信息

 4:生成的流程图具有层级关系,因为每一步有可能有多个接收方,比如流程的第一步在一个X轴上,第二步在相同的X轴上,以此类推,这样看起来比较有层次感,也不会乱

实现

前提是你会用echarts其他的图比如简单柱状图、饼状图等,知道其中的api,如果是初次接触,移步官方地址https://echarts.apache.org/zh/index.html

本例使用的是echarts关系图,x、y轴的方式进行布局

1:动态生成流程图

     这个好办,其实就是series里的data属性而已,自己看echarts关系图

2:根据待办、已办区分不同的背景颜色

   官方文档是默认的全局颜色,也就是series里的symbol属性

在这里,我们可以把它封装data里,去官网做个简单实现,所以在data里可以个性化不同的背景图

3:鼠标划过展示相应信息

  简单的文字可以直接用formatter函数用data里的字段进行展示,比如

tooltip: {
   formatter: function(x) {
      return  x.data.toolText;
    }
}

但是涉及到多些文字拼接的,就不好用了,从上面可以看出toolText依旧是data里的属性,所以思路就明确了,把多些文字封装到data里,比如toolText,在传到echart里就把字段组装好

4:生成的流程图具有层级关系

后台数据实现,考虑到以上分析,数据库中设置ordernum字段,开始步骤为1,每进行下一步就把ordernum加1,根据ordernum和数据量的大小来动态的判断x、y轴的坐标,其他数据和关系图api类似即可

相应的前端代码:

父页面逻辑

viewProcess为前台点击事件,根据流程的主ID获取完整流程图,横向单次流程目前设置长度为15步,可以自己根据需求来个性化,目前未找到好的办法,只有写死了15个order

<template>  
 <div>
    <!-- 其他隐藏,点击事件根据需求自己添加 -->
   
    <!-- 流程图公共弹窗 -->
    <relationBar v-bind="relationBarOptions" @close="clickCloseRelationBar"></relationBar>
     
  </div>
</template>

<script>
 
import relationBar from "./relationBar.vue";

export default {
  name: "xxx",
  props: {
    title: {
      type: String,
      default: ""
    },
    show: {
      type: Boolean,
      default: false
    },
  },
  data() {
    return {
    
      //======流程图属性 ======START
      relationBarOptions: {
        data: [],
        showFlag: false
      },
      order2: 1,
      order3: 1,
      order4: 1,
      order5: 1,
      order6: 1,
      order7: 1,
      order8: 1,
      order9: 1,
      order10: 1,
      order11: 1,
      order12: 1,
      order13: 1,
      order14: 1,
      order15: 1,
      dataInit: []
	 //======流程图属性 ======END
    };
  },
  components: {
    relationBar
  },
  watch: {
    
  },
  mounted() {
 
  },
  methods: {
    
    //查看流程图
    viewProcess() {
      this.order1 = 1;
      this.order2 = 1;
      this.order3 = 1;
      this.order4 = 1;
      this.order5 = 1;
      this.order6 = 1;
      this.order7 = 1;
      this.order8 = 1;
      this.order9 = 1;
      this.order10 = 1;
      this.order11 = 1;
      this.order12 = 1;
      this.order13 = 1;
      this.order14 = 1;
      this.order15 = 1;

       //echarts数据
      let echartsData = [];
	  //echarts关系数据
      let echartslinks = [];
      let dataAfterComBine = [];
      //根据insid获取数据
      let params = {};
      params.insId = this.editForm.id;
      params.mark = "2";
      this.$api
        .getProcessListByInsId({ params })
        .then(res => {
          if (res.code == 0) {
            let dataInitTemp = res.result;
           //解决名字重复问题,自己看官网API就知道原因了
            dataInitTemp.forEach(data => {
              let theSameNUm = 0;
              let deptname = data.deptname;

              res.result.forEach(data2 => {
                if (data2.deptname == deptname) {
                  theSameNUm++;
                }
                if (theSameNUm == 2) {
                  data2.deptname = data2.deptname + " ";
                }
                if (theSameNUm == 3) {
                  data2.deptname = data2.deptname + "  ";
                }
              });
            });

            this.dataInit = res.result;
          }
        })
        .then(res => {
          //################################计算位移 START###########################################
          //获取最大步长
          let maxOrderNum = 0;
          this.dataInit.forEach(d => {
            if (Number(d.ordernum) > maxOrderNum) {
              maxOrderNum = Number(d.ordernum);
            }
          });

          //初始值 x步长:1*200 y:1*100
          let addStepX = 1;
          let addStepY = 1;
          //判断 最大ordernum 根据ordernum和数据量进行X,Y判断,为了方便 使用*3计算
 
          for (let i = 3; i < 10; i++) {
            if (maxOrderNum >= i) {
              if (this.dataInit.length > i * 3) {
                addStepX = maxOrderNum - 1;
                addStepY = maxOrderNum - 1;
              }
            }
          }

          //添加数据
          this.dataInit.forEach(d => {
            let ordernumOfx = Number(d.ordernum) * 300 * Number(addStepX);
            let ordernumOfy = Number(d.ordernum) * 100 * Number(addStepY);

             //公共属性,开始节点特殊化
            let commnDataInit = {
              toolText:
                d.deptname +
                "</br>" +
                "新增人员: " +
                d.reciveuser +
                "</br>" +
                "新增时间: " +
                d.recivedate +
                "</br>" +
                "办理人员: " +
                d.opeuser +
                "</br>" +
                "办理时间: " +
                d.opedate,
              user: d.opeuser,
              date: d.opedate,
              name: d.deptname,
              x: ordernumOfx,
              text: d.currentcontent,
			    //背景图可以用网上的,这里是用nginx代理的服务器图片,根据自己需求来
              symbol:
               "image://http://XXXX.XXXX.XXXX:8096/XXX/processImg/redDone.jpg"
            };
             //公共属性,流程节点属性
            let commnData = {
              toolText:
                d.deptname +
                "</br>" +
                "签收人员: " +
                d.reciveuser +
                "</br>" +
                "签收时间: " +
                d.recivedate +
                "</br>" +
                "办理人员: " +
                d.opeuser +
                "</br>" +
                "办理时间: " +
                d.opedate +
                "</br>" +
                "意 见: " +
                d.currentcontent +
                "</br>",
              user: d.opeuser,
              date: d.opedate,
              name: d.deptname,
              x: ordernumOfx,
              text: d.currentcontent
            };

            if (d.ordernum == "1") {
              echartsData.push({
                ...commnDataInit,
                y: 0
              });
            } else {
              this.setEchartsData(
                echartsData,
                d,
                ordernumOfx,
                ordernumOfy,
                commnData
              );
            }

            let databeforeComBine = {
              id: d.id,
              name: d.deptname,
              childrens: []
            };
            dataAfterComBine.push(databeforeComBine);
            this.comBineLinks(d.id, databeforeComBine, this.dataInit);
          });

          dataAfterComBine.forEach(e => {
            e.childrens.forEach(element => {
              echartslinks.push({
                source: e.name,
                target: element
              });
            });
          });

          this.relationBarOptions.data = echartsData;
          this.relationBarOptions.links = echartslinks;
          this.relationBarOptions.showFlag = true;
        });
    },
    setEchartsData(echartsData, d, ordernumOfx, ordernumOfy, commnData) {
      if (d.status == "0") {
        commnData.symbol =
          "image://http://XXXX.XXXX.XXXX:8096/XXX/processImg/processImg/grennTodo.jpg";
      } else {
        commnData.symbol =
          "image://http://XXXX.XXXX.XXXX:8096/XXX/processImg/processImg/redDone.jpg";
      }

      if (d.ordernum == "2") {
        echartsData.push({
          ...commnData,
          y: this.order2 == 1 ? 0 : this.order2 * ordernumOfy
        });

        this.order2++;
      }
      if (d.ordernum == "3") {
        echartsData.push({
          ...commnData,
          y: this.order3 == 1 ? 0 : this.order3 * ordernumOfy
        });

        this.order3++;
      }
      if (d.ordernum == "4") {
        echartsData.push({
          ...commnData,
          y: this.order4 == 1 ? 0 : this.order4 * ordernumOfy
        });

        this.order4++;
      }

      if (d.ordernum == "5") {
        echartsData.push({
          ...commnData,
          y: this.order5 == 1 ? 0 : this.order5 * ordernumOfy
        });

        this.order5++;
      }

      if (d.ordernum == "6") {
        echartsData.push({
          ...commnData,
          y: this.order6 == 1 ? 0 : this.order6 * ordernumOfy
        });

        this.order6++;
      }

      if (d.ordernum == "7") {
        echartsData.push({
          ...commnData,
          y: this.order7 == 1 ? 0 : this.order7 * ordernumOfy
        });

        this.order7++;
      }
      if (d.ordernum == "8") {
        echartsData.push({
          ...commnData,
          y: this.order8 == 1 ? 0 : this.order8 * ordernumOfy
        });

        this.order8++;
      }
      if (d.ordernum == "9") {
        echartsData.push({
          ...commnData,
          y: this.order9 == 1 ? 0 : this.order9 * ordernumOfy
        });

        this.order9++;
      }
      if (d.ordernum == "10") {
        echartsData.push({
          ...commnData,
          y: this.order10 == 1 ? 0 : this.order10 * ordernumOfy
        });

        this.order10++;
      }
      if (d.ordernum == "11") {
        echartsData.push({
          ...commnData,
          y: this.order11 == 1 ? 0 : this.order11 * ordernumOfy
        });

        this.order11++;
      }
      if (d.ordernum == "12") {
        echartsData.push({
          ...commnData,
          y: this.order12 == 1 ? 0 : this.order12 * ordernumOfy
        });

        this.order12++;
      }
      if (d.ordernum == "13") {
        echartsData.push({
          ...commnData,
          y: this.order13 == 1 ? 0 : this.order13 * ordernumOfy
        });

        this.order13++;
      }
      if (d.ordernum == "14") {
        echartsData.push({
          ...commnData,
          y: this.order14 == 1 ? 0 : this.order14 * ordernumOfy
        });

        this.order14++;
      }
      if (d.ordernum == "15") {
        echartsData.push({
          ...commnData,
          y: this.order15 == 1 ? 0 : this.order15 * ordernumOfy
        });

        this.order15++;
      }
    },

    comBineLinks(id, databeforeComBine, data) {
      data.forEach(d => {
        if (d.parentId == id) {
          databeforeComBine.childrens.push(d.deptname);
        }
      });
    },
    processTypeFlt(row) {
      //0下发1请示2反馈3退回4结束
      switch (row.processType) {
        case "0":
          if (row.ordernum == "1") {
            return "下发";
          } else {
            return "流转";
          }

          break;
        case "1":
          return "请示";
          break;
        case "2":
          return "回报";
          break;
          break;
        case "4":
          return "结束";
          break;
        default:
          if (row.iscopy == "0") {
            if (row.ordernum == "1") {
              return "新增";
            } else {
              return "签收";
            }
          } else {
            return "接收";
          }
      }
    }

    //################################计算位移 END###########################################
  },
  filters: {
 
  }
};
</script>

<style lang="scss">
 
</style>

子页面(echarts组件):

<template>
  <el-dialog :visible="show" @close="clickClose()" append-to-body width="60%">
    <template slot="title">
      <span style="width: calc(100% - 60px);display: inline-block;" class="single-line">
        <slot name="title">{
   
   {dialogtitle}}</slot>
      </span>
    </template>
    <div class="relationBar">
      <div class="relationBarDiv" ref="relationEcharts"></div>
    </div>
    <span slot="footer" class="dialog-footer">
      <el-button>关 闭</el-button>
    </span>
  </el-dialog>
</template>

<script>
var option = {
  title: {
    text: "",
    x: "center",
    textStyle: {
      fontWeight: "normal" //标题颜色
    }
  },
  //个性化划过事件
  tooltip: {},
  series: [
    {
      // symbol:"image://data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7",
      // symbol: "rect", //circle圆形  rect矩形
      type: "graph", //关系图
      layout: "none", // 图的布局。[ default: 'none' ] 'none' 不采用任何布局,使用节点中提供的 x, y 作为节点的位置。 'circular' 采用环形布局;'force' 采用力引导布局.
      symbolSize: 50,
      roam: true,
      label: {
        show: true
      },
      edgeSymbol: ["circle", "arrow"],
      edgeSymbolSize: [4, 10],
      edgeLabel: {
        fontSize: 20
      },
      //color:'#A6FFA6',
      data: [],
      links: [],
      lineStyle: {
        opacity: 0.9,
        width: 2,
        curveness: 0,
        //color: '#000',          // 线的颜色[ default: '#aaa' ]
        //           width: 1,               // 线宽[ default: 1 ]
        //           type: 'solid',          // 线的类型[ default: solid ]   'dashed'    'dotted'
        //           opacity: 0.5,           // 图形透明度。支持从 0 到 1 的数字,为 0 时不绘制该图形。[ default: 0.5 ]
        //           curveness: 0            // 边的曲度,支持从 0 到 1 的值,值越大曲度越大。[ default: 0 ]
      }
    }
  ]
};
export default {
  name: "relationBar",
  props: {
    data: {
      type: Array,
      default: () => {
        [];
      }
    },
    links: {
      type: Array,
      default: () => {
        [];
      }
    },
    title: {
      type: String,
      default: ""
    },
    showFlag: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      dialogtitle: "流程关系图",
      show: false
    };
  },
  created() {},
  watch: {
    showFlag: {
      handler(n, o) {
        this.show = n;
        if (n) {
          this.initEcharts();
        }
      },
      immediate: true
    }
  },
  mounted() {
    //this.initEcharts();
  },
  methods: {
    clickClose() {
      this.$emit("close");
    },
    setOption(data) {
      let op = JSON.parse(JSON.stringify(option));
     
      op.series[0].data = this.data;
      op.series[0].links = this.links;
      op.tooltip = {
        formatter: function(x) {
           return  x.data.toolText;
        }
      };
     
      return op;
    },
    initEcharts() {
      this.$nextTick(() => {
        let ctx = this;

        let myChart = ctx.$echarts.init(ctx.$refs.relationEcharts);
        myChart.setOption(ctx.setOption(ctx.data));
        ctx.$refs.relationEcharts.style.width = "100%";
      });
    }
  }
};
</script>

<style lang="scss">
.relationBar {
  width: 100%;
  height: 700px;
  border: #e3e3e3 1px solid;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  overflow: scroll;
  .relationBarDiv {
    width: 100%;
    height: 100%;
    min-height: 700px;
    min-width: 250px;
  }
}
</style>

最终效果,目前是第3步,步数增加,页面会相应变化:红色图片代表已办、绿色图片代表待办,流程弹窗具有办理的意见

猜你喜欢

转载自blog.csdn.net/CarryBest/article/details/106764921
今日推荐