精华内容
下载资源
问答
  • vue 甘特图插件

    万次阅读 2019-06-17 11:18:25
    官网地址:https://dhtmlx.com/blog/use-dhtmlxgantt-vue-js-framework-demo/
    展开全文
  • Vue 甘特图

    千次阅读 热门讨论 2020-10-12 14:07:11
    vue甘特图,先大致介绍下核心功能: (1)横轴、纵轴拖拽; (2)自定义监听点击事件(双击、右键等)(3)任务之间显示父子层级关系;(4)左侧列表信息,右侧时间轴表示任务;(5)每个任务可以订制样式,并且...

    vue做甘特图,先大致介绍下核心功能: (1)横轴、纵轴拖拽; (2)自定义监听点击事件(双击、右键等)(3)任务之间显示父子层级关系;(4)左侧列表信息,右侧时间轴表示任务;(5)每个任务可以订制样式,并且可以动态修改样式;(6)自定义时间粒度显示(小时、天、星期、月、年);(7)支持大批量数据渲染;(8) 支持同行多节点渲染;(9)支持选中,以及批量选中;(9)优秀的扩展性,支持第三方插件。等等还有其他的一些功能。这里先看一下效果图:

     

     

     

     

      接下来会介绍用什么实现的,怎么使用,怎么添加拖拽、点击等各种功能,我以vue为例进行开发。

    1、使用GSTC做甘特图开发

      Git项目地址:https://github.com/neuronetio/gantt-schedule-timeline-calendar#weekendhighlight-plugin

      官方vue实例:https://github.com/neuronetio/vue-gantt-schedule-timeline-calendar

      npm指令: npm i gantt-schedule-timeline-calendar

      官方做了 3 大主流框架的封装,具体看Git链接,这里我也附上了vue版本的 npm 包地址。

      基本使用如下:  ps:文章末尾我会贴一个完整的代码,如果是vue项目可以直接复制查看效果。下边这个是个极度阉割的。

    <template>
        <GSTC :config="config" />
    </template>
    <script>
    import GSTC from "vue-gantt-schedule-timeline-calendar";
    export default {
      data(){
        return {
          config: {
            height: 500,
            list: {
              rows: {
                "1": { id: "1", order: '订单1', },
              },
              columns: {
                data: {
                  id: { id: "id", data: "id", width: 50, header: { content: "序号" } },
                }
              }
            },
            chart: {
              items: {
                "1": { id: "1", rowId: "1", time: { start: new Date().getTime() + 1 * 24 * 60 * 60 * 1000, end: new Date().getTime() + 2 * 24 * 60 * 60 * 1000 } }
              }
            },
          },
          subs: []
        }
      },
      beforeDestroy() { this.subs.forEach(unsub => unsub()); }
    }
    </script>
    <style lang="less" scoped>
      .wrapper .gantt-elastic__grid-line-time {
        display: none;
      }
    </style>
    
     

     

    基础使用已经贴代码了,不做赘述,不清楚的查看官方示例,接下来主要说核心功能如何配置,这方面官方描述的不是很清楚,但是Git的 issues 好多问题都关闭了,基本大部分问题都可以查到。

    1、基础展示,左侧多列表格展示

            

     

     

     这个主要配置config中的 list 属性,

      rows 代表左侧表格的行属性,key值是每行的id,多个key就有多行,通常都以数字做key值, 内部 具体属性是列信息。比如 order label line 等都是列信息,这个会一一对应到指定列。

        parentID 是父节点配置,一般配置了父节点,就会在 甘特图 中展示出父子层级来。

        expanded 是展开属性,默认false,父子层级是合上的,折叠隐藏子节点。如果想默认展示需要每个节点都加上这个属性。

      columns 代表左侧表格的列属性,key唯一就是列关键字。

        data 属性,是列,可以有多个属性,每个代表一列

          id 当前列的id

          data 列标识,和rows中每行的数据的字段唯一对应,比如  order、line 等

          isHTML 是否要展示HTML,默认false。  这个直接关系到content、html字段用哪个

          width 当前列宽度

          expander 是否显示层级,默认false不展示,设置为true,会展示出父子层级来,一般我们仅设置一列,当然设置多列也行。

          header 配置表头内容的

            content 表头想显示的内容

            html 写HTML,用来订制表头样式的,内容就是HTML,行内css

        percent 是左侧表格总宽度占甘特图的百分比,0就直接隐藏表格

        minWidth:是左侧表格的最小宽度

    list: {
              rows: {
                "1": {
                  id: "1",
                  order: '订单1',
                  label: "压缩机",
                  line: '线体1',
                  expanded: true
                },
                "3": {
                  id: "3",
                  order: '订单3',
                  label: "箱体",
                  line: '线体3',
                  parentId: '2',
                }
              },
              columns: {
                data: {
                  id: {
                    id: "id",
                    data: "id",
                    width: 50,
                    expander: true,
                    header: { content: "序号" }
                  },
                  order: {
                    id: "order",
                    data: "order",
                    header: { content: "生产订单" }
                  },
                  label: {
                    id: "label",
                    data: "label",
                    header: { content: "描述" }
                  }
                }
              }
            }

     

    2、右侧任务排列显示(包括订制样式)

          

     

    这个主要配置config中的 chart 属性,

       time 配置时间轴

        from 左侧开始时间,填写毫秒数

        to 右侧结束时间,填写毫秒数

        zoom 显示层级,10-22,越大,时间粒度展示的越大,越小,显示越精细,最小到5分钟

      items 任务快配置,注意这个可以同行若干任务展示

        id 当前任务的id

        rowId 左侧表格 rows 的id,通过这个关联,渲染到某一行

        label 当前任务的名称,会默认展示在任务中

        time 任务的开始、结束时间

          start 开始时间,填写毫秒数

          end 结束时间, 填写毫秒数

        style 订制样式,是个对象,写过jsx写法,写过react 、vue jsx 的应该都不默认,这里举个简单的例子,订制任务div的背景色 圆角等样式  { background: 'red', borderRadius: '3px' }

    chart: {
              time: {
                from: new Date().getTime() - 2 * 24 * 60 * 60 * 1000,
                to: new Date().getTime() + 8 * 24 * 60 * 60 * 1000,
                zoom: 22,    
              },
              items: {
                "1": {
                  id: "1",
                  rowId: "1",
                  label: "Item 1",
                  time: {
                    start: new Date().getTime() + 1 * 24 * 60 * 60 * 1000,
                    end: new Date().getTime() + 2 * 24 * 60 * 60 * 1000
                  },
                  style: {  // 每个块的样式
                    background: 'blue'
                  }
                },
                "21": {
                  id: "21",
                  rowId: "2",
                  label: "Item 2-1",
                  time: {
                    start: new Date().getTime() + 2 * 24 * 60 * 60 * 1000,
                    end: new Date().getTime() + 3 * 24 * 60 * 60 * 1000
                  }
                }
              }
            }

     

    3、配置右侧横轴的时间显示

         

     

     这个主要配置config中的 locale 属性,时间的语言环境配置,这里看文档详细些,下面只详说2个属性,

      weekdays 配置 每周显示的文案   主要是做国际化用的

      months 配置月的,也是做国际化的

    locale: {
              name: "zh",
              Now: "Now",
              weekdays:["周日","周一","周二","周三","周四","周五","周六"],
              months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],
            }

     

    4、监听鼠标右击事件

          

     

     这个主要配置config中的 actions 属性,他是对象,以下是他所有能监听dom,很多,这篇博客就只介绍人物块的事件监听,其他的不做一一赘述了

    • main
    • list
    • list-column
    • list-column-header
    • list-column-header-resizer
    • list-column-header-resizer-dots
    • list-column-row
    • list-column-row-expander
    • list-column-row-expander-toggle
    • list-toggle
    • chart
    • chart-calendar
    • chart-calendar-date
    • chart-timeline
    • chart-timeline-grid
    • chart-timeline-grid-row
    • chart-timeline-grid-row-block
    • chart-timeline-items
    • chart-timeline-items-row
    • chart-timeline-items-row-item

      这个监听函数会接收2个参数,element  和 data ,一个是dom,另一个是 任务节点的数据。根据官方要求,监听函数必须返回一个对象,此对象必须包含 update  destroy 2个方法,分别是位置更新和销毁时需要执行的方法。具体写法请见如下代码:

    actions: {
          'chart-timeline-items-row-item': [this.addListenClick] // 监听右击事件
    }
    
    methods:{
        addListenClick(element, data) {
          const onClick = (e) => {
            e.preventDefault()
            // console.log(data)
            this.modal = {
              visible: true,
              title: data.item.label,
              data
            }
            return false
          }
          element.addEventListener('contextmenu', onClick);
          return {
            update(element, newData) {
              data = newData;
            },
            destroy(element, data) {
              element.removeEventListener('click', onClick);
            }
          };
        },
        closeModal() {
          this.modal = {
            visible: false,
            title: '',
            data: {}
          }
        }
      },

    5、任务的横轴、纵轴拖动

           

     

     

    这个主要配置config中的 plugins 属性,

      ItemMovement 插件,这个是官方开发的用来拖拽任务的插件。这个包的插件系统做的很好,官方提供了几种不错的插件,同时还支持其他的第三方插件,有兴趣的可以自己试试,这里先介绍拖拽插件,

         moveable 拖拽的方向, x 支持横轴拖拽;   y 支持纵轴拖拽;  true 横轴、纵轴都可以拖拽; false 禁止拖拽

        resizeable 是否可以拖拽,true开启拖拽

        resizerContent 拖拽的图标,直接写HTML,可以自己定制拖拽图标的样式

        collisionDetection: 拖拽过程中是否允许元素重叠, true 不允许重叠

        ghostNode  false 不展示重影节点

        snapStart 拖拽开始时间点回调,这个比较机制特殊,拖拽位置的时候触发这个方法,参数接收开始时间  时间变化 当前节点数据,默认是毫秒级的刷新,会卡,我们做if判断1小时拖拽

        snapEnd 拖拽结束时间点回调,这个是拖动任务块大小时触发,接收结束时间 时间段。用法同上。具体请看如下代码:

    plugins: [
              // 拖动 x 横向, y 纵向
              ItemMovement({
                moveable: 'x',
                resizerContent: '<div class="resizer">-></div>',
                ghostNode: false,
                snapStart(time, diff, item) {
                  if(Math.abs(diff) > 14400000) {
                    return time + diff
                  }
                  return time
                },
                snapEnd(time, diff, item) {
                  if(Math.abs(diff) > 14400000) {
                    return time + diff
                  }
                  return time
                }
              })
            ]

     

    6、选中任务

          

     

     

    这个主要配置config中的 plugins 属性,

      Selection插件,单个选中、批量选中插件。

        grid 能否选中单元格

        items  能否选中任务

        rows  能否选中行

        rectStyle 矩形样式

        selected 选中的回调

        deselected  取消选中的回调

        canSelected  可选中的的回调,用来过滤哪些可以选中

        canDeselected 可取消选中的回调,用来过滤哪些可以取消选中

    plugins: [
              Selection({
                items: false,
                rows: false,
                grid: true,
                rectStyle: { opacity: '0.0' }, 
                canSelect(type, currentlySelecting) {
                  if (type === 'chart-timeline-grid-row-block') {
                    return currentlySelecting.filter(selected => {
                      if (!selected.row.canSelect) return false;
                      for (const item of selected.row._internal.items) {
                        if (
                          (item.time.start >= selected.time.leftGlobal && item.time.start <= selected.time.rightGlobal) ||
                          (item.time.end >= selected.time.leftGlobal && item.time.end <= selected.time.rightGlobal) ||
                          (item.time.start <= selected.time.leftGlobal && item.time.end >= selected.time.rightGlobal)
                        ) {
                          return false;
                        }
                      }
                      return true;
                    });
                  }
                  return currentlySelecting;
                },
                canDeselect(type, currently, all) {
                  if (type === 'chart-timeline-grid-row-blocks') {
                    return all.selecting['chart-timeline-grid-row-blocks'].length ? [] : currently;
                  }
                  return [];
                }
              })
            ]

    小结:

      以上就是整个甘特图的使用了,这是我用过最符合项目需求的甘特图,他的开发团队也在持续的维护这个项目,很赞。

      最后贴一段完整的 vue 示例代码:

    <template>
      <div class="wrapper">
        <GSTC :config="config" />
        <infor-modal
          :visible="modal.visible"
          :title="modal.title"
          :dataSource="modal.data"
          @handleModal="closeModal"
        />
      </div>
    </template>
    
    <script>
    import GSTC from "vue-gantt-schedule-timeline-calendar";
    import ItemMovement from "gantt-schedule-timeline-calendar/dist/ItemMovement.plugin.js"
    import Selection from "gantt-schedule-timeline-calendar/dist/Selection.plugin.js"
    import inforModal from "./inforModal"
    
    export default {
      components:{
        GSTC,
        inforModal
      },
      props:{},
      data(){
        return {
          config: {
            height: 500,
            list: {
              // 行属性
              rows: {
                "1": {
                  id: "1",
                  order: '订单1',
                  label: "压缩机",
                  line: '线体1',
                  expanded: true
                },
                "3": {
                  id: "3",
                  order: '订单3',
                  label: "箱体",
                  line: '线体3',
                  parentId: '2',
                },
                "4": {
                  id: "4",
                  order: '订单4',
                  label: "空调总装",
                  line: '线体4',
                },
                "2": {
                  id: "2",
                  order: '订单2',
                  label: "门体",
                  parentId: '1',
                  line: '线体2',
                  expanded: true
                },
                "5": {
                  id: "5",
                  order: '订单5',
                  label: "冰箱总装",
                  line: '线体5',
                },
                "6": {
                  id: "6",
                  order: '订单6',
                  label: "洗衣机总装",
                  line: '线体6',
                },
              },
              // 列定义
              columns: {
                data: {
                  id: {
                    id: "id",
                    data: "id",
                    width: 50,
                    header: {
                      content: "序号"
                    }
                  },
                  order: {
                    id: "order",
                    data: "order",
                    width: 120,
                    header: {
                      content: "生产订单"
                    }
                  },
                  label: {
                    id: "label",
                    data: "label",
                    width: 120,
                    expander: true,
                    header: {
                      content: "描述"
                    }
                  },
                  line: {
                    id: "line",
                    data: "line",
                    width: 120,
                    header: {
                      content: "线体"
                    }
                  },
                }
              }
            },
            chart: {
              time: {  // 时间轴开始截至,
                from: new Date().getTime() - 2 * 24 * 60 * 60 * 1000,
                to: new Date().getTime() + 8 * 24 * 60 * 60 * 1000,
                zoom: 22,    // 10-22 缩放,默认 Shift + 滚轮, 默认缩放展示时间粒度, 一共有 小时、天、周、月、年
              },
              items: {
                "1": {
                  id: "1",
                  rowId: "1",
                  label: "Item 1",
                  time: {
                    start: new Date().getTime() + 1 * 24 * 60 * 60 * 1000,
                    end: new Date().getTime() + 2 * 24 * 60 * 60 * 1000
                  },
                  style: {  // 每个块的样式
                    background: 'blue'
                  }
                },
                "21": {
                  id: "21",
                  rowId: "2",
                  label: "Item 2-1",
                  time: {
                    start: new Date().getTime() + 2 * 24 * 60 * 60 * 1000,
                    end: new Date().getTime() + 3 * 24 * 60 * 60 * 1000
                  }
                },
                "22": {
                  id: "22",
                  rowId: "2",
                  label: "Item 2-2",
                  time: {
                    start: new Date().getTime() + 3 * 24 * 60 * 60 * 1000,
                    end: new Date().getTime() + 4 * 24 * 60 * 60 * 1000
                  }
                },
                "3": {
                  id: "3",
                  rowId: "3",
                  label: "Item 3",
                  time: {
                    start: new Date().getTime() + 3 * 24 * 60 * 60 * 1000,
                    end: new Date().getTime() + 5 * 24 * 60 * 60 * 1000
                  }
                },
                "4": {
                  id: "4",
                  rowId: "4",
                  label: "Item 4",
                  time: {
                    start: new Date().getTime() + 2 * 24 * 60 * 60 * 1000,
                    end: new Date().getTime() + 5 * 24 * 60 * 60 * 1000
                  }
                },
                "5": {
                  id: "5",
                  rowId: "5",
                  label: "Item 5",
                  time: {
                    start: new Date().getTime() + 3 * 24 * 60 * 60 * 1000,
                    end: new Date().getTime() + 5 * 24 * 60 * 60 * 1000
                  }
                },
                "6": {
                  id: "6",
                  rowId: "6",
                  label: "Item 6",
                  time: {
                    start: new Date().getTime() + 5 * 24 * 60 * 60 * 1000,
                    end: new Date().getTime() + 6 * 24 * 60 * 60 * 1000
                  }
                },
              }
            },
            locale: {
              name: "zh",
              Now: "Now",
              weekdays:["周日","周一","周二","周三","周四","周五","周六"],
              months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],
            },
            actions: {
              'chart-timeline-items-row-item': [this.addListenClick] // 监听右击事件
            },
            plugins: [
              // 拖动 x 横向, y 纵向
              ItemMovement({
                moveable: 'x',
                resizerContent: '<div class="resizer">-></div>',
                ghostNode: false,
                collisionDetection: false,
                snapStart(time, diff, item) {
                  if(Math.abs(diff) > 14400000) {
                    return time + diff
                  }
                  return time
                },
                snapEnd(time, diff, item) {
                  if(Math.abs(diff) > 14400000) {
                    return time + diff
                  }
                  return time
                }
              }),
              Selection({
                items: false,
                rows: false,
                grid: true,
                rectStyle: { opacity: '0.0' }, 
                canSelect(type, currentlySelecting) {
                  if (type === 'chart-timeline-grid-row-block') {
                    return currentlySelecting.filter(selected => {
                      if (!selected.row.canSelect) return false;
                      for (const item of selected.row._internal.items) {
                        if (
                          (item.time.start >= selected.time.leftGlobal && item.time.start <= selected.time.rightGlobal) ||
                          (item.time.end >= selected.time.leftGlobal && item.time.end <= selected.time.rightGlobal) ||
                          (item.time.start <= selected.time.leftGlobal && item.time.end >= selected.time.rightGlobal)
                        ) {
                          return false;
                        }
                      }
                      return true;
                    });
                  }
                  return currentlySelecting;
                },
                canDeselect(type, currently, all) {
                  if (type === 'chart-timeline-grid-row-blocks') {
                    return all.selecting['chart-timeline-grid-row-blocks'].length ? [] : currently;
                  }
                  return [];
                }
              })
            ]
          },
          modal: {
            visible: false,
            title: '',
            data: {}
          },
          subs: []
        }
      },
      watch:{},
      computed:{},
      methods:{
        addListenClick(element, data) {
          const onClick = (e) => {
            e.preventDefault()
            // console.log(data)
            this.modal = {
              visible: true,
              title: data.item.label,
              data
            }
            return false
          }
          element.addEventListener('contextmenu', onClick);
          return {
            update(element, newData) {
              data = newData;
            },
            destroy(element, data) {
              element.removeEventListener('click', onClick);
            }
          };
        },
        closeModal() {
          this.modal = {
            visible: false,
            title: '',
            data: {}
          }
        }
      },
      created(){},
      mounted(){
      },
      beforeDestroy() {
        this.subs.forEach(unsub => unsub());
      }
    }
    </script>
    <style lang="less" scoped>
      .wrapper .gantt-elastic__grid-line-time {
        display: none;
      }
    </style>

    转自:https://www.cnblogs.com/pengfei-nie/p/13092159.html

    展开全文
  • vue插件甘特图

    万次阅读 2019-05-15 15:23:57
    vue插件甘特图 下载包 npm install dhtmlx-gantt --save 创建Gantt.vue文件 <template> <div ref="gantt"></div> </template> <script> import 'dhtmlx-gantt' export ...

    vue插件之甘特图

    甘特图

    1. 下载包

    npm install dhtmlx-gantt --save

    1. 创建Gantt.vue文件
    <template>
      <div ref="gantt"></div>
    </template>
    
    <script>
    import 'dhtmlx-gantt'
    export default {
      name: 'gantt',
      props: {
        tasks: {
          type: Object,
          default () {
            return {data: [], links: []}
          }
        }
      },
    
      mounted: function () {
        gantt.init(this.$refs.gantt)
        gantt.parse(this.$props.tasks)
      }
    }
    </script>
    
    <style>
        @import "dhtmlx-gantt/codebase/dhtmlxgantt.css";
    </style>
    

    在需要的甘特图vue文件中写入以下代码

    <template>
      <div class="container">
        <gantt class="left-container" :tasks="tasks"></gantt>
      </div>
    </template>
    
    <script>
    import Gantt from './components/Gantt.vue';
    
    export default {
      name: 'app',
      components: {Gantt},
      data () {
        return {
          tasks: {
            data: [
            {
    			text: 'Test001-001',//任务名
    			start_date: '19-04-2017',//开始时间
    			id: 1,//任务id
    			duration: 13,//任务时长,从start_date开始计算
    			progress: 0.6,//任务完成情况,进度
    			parent: 2,//父任务ID
    			user: "李四",//成员
    			planned_end:'19-04-2017', //计划开始时间
    			planned_start:'10-04-2017',//计划结束时间
    			show:false,
    			open: true,//默认是否打开
    			type: 'project'// gantt.config.types.milestone为里程碑类型
    			        // project为项目任务类型,也就是摘要任务,
    			        // task为普通任务类型
    			},
              {id: 2, text: 'Task #1', start_date: '15-04-2017', duration: 3, progress: 0.6},
              {id: 3, text: 'Task #2', start_date: '18-04-2017', duration: 3, progress: 0.4}
            ],
            links: [// links为任务之间连接的线
              {id: 1, source: 1, target: 2, type: '0'}//source根源 target目标 也就是从id为1的指向id为2的
            //type:'0'是从1任务完成到2任务开始,type:'1'是1任务开始到2任务开始,
            //type:'2'是从1任务完成到2任务完成,type:'3'是从1任务开始到2任务完成
            ]
          },
        }
      }
    }
    </script>
    

    当然,每一个项目对应的甘特图都有自己的样式,希望自己慢慢修改。

    展开全文
  • echarts vue 甘特图实现

    2018-09-30 11:08:00
    厂家机型故障分析 ...--柱状为例 --> <script src="/static/js/component/dateType.js"></script> <script src="/static/js/component/chart-wrapper.js"></script> ...
    <{extends file="../main.tpl" }>
    
    <{block name="html_header_title" append}>
    <title>厂家机型故障分析</title>
    <{/block}>
    
    <{block name="html_header_css" append}>
    <style>
    .yn-main-wrapper__cloumn{
        flex:1;
        display:flex;
        flex-direction: column;
    }
    .yn-br__graph{
        flex:1;
    }
    .yn-br__graph:first-child {
        display:flex;
    }
    
    .yn-br__graph-left{
        flex:1;
        box-sizing:border-box;
        position:relative;
    }
    .yn-chart__title {
        position:absolute;
        top:10px;
        z-index:2;
        left:50%;
        transform:translate3D(-50%,0,0);
        display:flex;
    }
    .yn-chart__title-item {
        display:inline-block;
        margin-right:10px;
        font-size:12px;
        display:flex;
        align-items:center;
    }
    .yn-chart__title-item > span {
        display:inline-block;
        width:18px;
        height:18px;
        margin-right:10px;
    }
    .yn-br__graph--body{
        box-sizing:border-box;
    }
    .yn-line__graph--title,
    .yn-br__graph--title {
        margin-bottom:22px;
    }
    /*排名的表格padding*/
    .yn-br__graph--range{
        padding:0px 0px 0px 10px;
        box-sizing:border-box;
    }
    .wrap-check-select {
        width:240px;
    }
    .search-form__item{
        margin-right:20px;
        display:flex;
        justify-content:space-between;
        align-items:center;
        margin-bottom:10px;
        
    }
    
    .search-form {
        padding-left: 20px;
    }
    .check-select{
        height:30px;
    }
    </style>
    <{/block}>
    
    <{block name="body_content" }>
    <div id="root">
    <!--搜索区域 -->
        <div id="forTitle">
            <yn-title
                :title="'故障趋势分析'"
            ></yn-title>
        </div>
        <script>
            new Vue({el: '#forTitle'})
        </script>
        <div class="search-form-wrapper" id='vue-head'>
            <div class="search-form angle-border clearfix" >
                <div class="search-form__item">
                    <span style="margin-right:10px;">时间范围</span>
                    <input class="date-picker-input" type="text" id='range-date'>
                </div>
                <div class="search-form__item">
                    <label class=search-form__item__label>分析维度</label>
                    <div class="search-form__item__control search-form__item__control--select">
                        <div class='el-select-wrapper'>
                            <img src="/static/images/select-down-arrow.png" class="select-down-arrow" alt="">
                            <el-select v-model="latituduesValue" placeholder="请选择">
                                <el-option
                                    v-for="(group,index) in analysisLatitudues"
                                    :key="index"
                                    :label="group.label"
                                    :value="group.value"
                                    >
                                </el-option>
                            </el-select>
                        </div>
                    </div>
                </div>
                <div class="search-form__item">
                    <label class=search-form__item__label>风场</label>
                    <div class="search-form__item__control search-form__item__control--select">
                        <div class='el-select-wrapper'>
                            <img src="/static/images/select-down-arrow.png" class="select-down-arrow" alt="">
                            <el-select v-model="farmValue" placeholder="请选择">
                                <el-option
                                    v-for="group in options_farm"
                                    :key="group.value"
                                    :label="group.text"
                                    :value="group.value"
                                    >
                                </el-option>
                            </el-select>
                        </div>
                    </div>
                </div>
                <div class='wrap-check-select search-form__item'>
                    <div style="width:60px">机组</div>
                    <div id='group-model' class='search-form__item__control'>
                        <check-select2 :datas="forSaveFantype" @get-select-value2='getSelectValue'></check-select2>
                    </div>
                </div>
                <div class="search-form__item" style='float:right;'>
                    <button @click="search" class='search-btn'>查询</button>
                </div>
            </div>
        </div>
        <!--main -->
        <div class="yn-main-wrapper" id="app">
            <div class="yn-main-wrapper__cloumn">
                <div  @click.stop="bodyClick"  class="yn-br__graph">
                    <div v-loading="loading" class="yn-br__graph-left">
                        <div class="yn-chart__title">
                            <div @click.stop="barClick(item)" style="cursor:pointer" class="yn-chart__title-item" v-for="(item,index) in status" :key="index">
                                <span  :style="backgroundComputed(item)"></span>
                                {{item}}
                            </div>
                        </div>
                        <yn-chart-wrapper style="padding:32px 10px 0px 10px;">
                          <template slot="chartInfo">
                              <!--柱状图为例 -->
                              <div ref="scatter" class="yn__graph--body yn-br__graph--body yn-scroll">
                                  
                              </div>
                          </template>
                      	</yn-chart-wrapper>
                    </div>
                </div>
            </div>
        </div>
    </div>
    
    <{/block}>
    
    <{block name="body_main_js" append}>
    <script src="/static/js/component/dateType.js"></script>
    <script src="/static/js/component/chart-wrapper.js"></script>
    <script src="/static/js/component/select2.js"></script>
    <script>
        var INDEX_NAME = '能量可利用率(%)';
        var allData = {};
        var STARTDATA = '<{$startDate}>';
        var ENDDATA = '<{$endDateD}>';
        //头部
        
        var vm = new Vue({
            el: '#vue-head',
            data: function(){
                return {
                    options_farm:[],
                    //风场
                    farmValue:'',
                    //机组
                    farmModelValue:'',
                    //风场型号
                    farmModel:[],
                    //风场详细型号
                    farmFantype:[],
                    // 风场选中机型的list
                    farmModelList:{},
                    //analysisLatitudues分析维度
                    analysisLatitudues:[{label:'系统',value:'system'},{label:'检修',value:'repair'}],
                    //维度的value值
                    latituduesValue:"",
                    backValue:'',
                    //选中机型的value
                    groupValue:'',
                    province : '云南'
                }
            },
            methods: {
                getSelectValue: function (data) {
                    this.groupValue = data.join(',');
                },
                search: function () {
                    var rangeData = $('#range-date').val();
                    var arr = _.split(rangeData, ' - ', 2);
                    var startData = arr[0];
                    var endDate = arr[1];
                    if(!this.province || !startData || !endDate || !this.farmValue || !this.groupValue || !this.latituduesValue){
                        this.$message(
                            {
                                showClose: true,
                                message: '请填写需要筛选的数据!',
                                type: 'warning',
                                customClass:'messageClass',
                                iconClass:'icon-yn-warn'
                            }
                        )
                        return;
                    }
                    allData.ajaxObj={
                        province:this.province,
                        startDate: startData,
                        endDate: endDate,
                        farm:this.farmValue,
                        fantype:this.groupValue,
                        //新的属性
                        dimension:this.latituduesValue
                    }
                    //调用下面vue的初始化表的方法
                    vmRoot.shearchEcharts(allData.ajaxObj);
                }
            },
            computed: {
                forSaveFantype : function(){
                    var that = this;
                    that.farmModel=[];
                    that.farmFantype=[];
                    that.farmModelList =all_provinceData[this.farmValue];
                    _.forIn(that.farmModelList, function(value, key) {
                        that.farmModel.push({key:key,value:key,checked:true});
                        that.farmFantype.push(key);
                    });
                    that.backValue = that.farmFantype.join(',');
                    that.groupValue = that.backValue;
                    return that.farmModel;
                },
            },
            mounted: function () {
                var str = localStorage.getItem('basicInfo');
                var baseInfoObj = JSON.parse(str); 
                this.options_farm = all_provinceSelect;
                this.farmValue = this.options_farm[0].value;
                this.farmModelList = all_provinceSelect[this.farmValue];
                this.latituduesValue = 'system';
                //初始化时间插件
                laydate.render({
                    elem: '#range-date',
                    type: 'month',
                    range: true,
                    min:baseInfoObj.startDate,
                    max:baseInfoObj.endDateD
                });
                var str = STARTDATA + ' - ' + ENDDATA;
                $('#range-date').val(str);
            }
        })
        function changeAlgorithm(algorithm) {
            vm.search();
        }
    </script>
    <script>
        var FANTYPE = '<{$basicInfoJson}>';
        var FARMNAMES = JSON.parse(FANTYPE);
        var vmRoot = new Vue({
            el: '#app',
            data:function(){
                return {
                    option: {},
                    //时序图图标
                    myChart:null,
                    types: [],
                    categories: [],
                    status : [],
                    startTime:'',
                    endTime:'',
                    //头部传来的时间
                    vmStartTime : '',
                    vmEndTime : '',
                    dataCount:10,
                    data:[],
                    //对应的名称
                    farmnames : {},
                    //为不同的状态分配不同的颜色
                    colorList : [
                        '#ffee58',
                        '#2196f3',
                        '#1de9b6',
                        '#f9a825',
                        '#e040fb',
                        '#d32f2f',
                        '#43a047',
                        '#26c6da',
                        '#3d5afe',
                        '#9ccc65',
                        '#ff5722',
                        '#9c27b0',
                        '#ccff90',
                        '#7b1fa2',
                        '#0288d1',
                    ],
                    peerColor: {},
                    //控制请求接口显示不显示
                    loading : false,
                    //请求锁
                    searchLock : false,
                    //存入数据
                    totalData : [],
                }
            },
            methods : {
                shearchEcharts:function (data){
                    if(this.searchLock){
                        this.$message(
                            {
                                showClose: true,
                                message: '请等数据加载完成!',
                                type: 'warning',
                                customClass:'messageClass',
                                iconClass:'icon-yn-warn'
                            }
                        )
                        return;
                    }
                    this.searchLock= true;
                    //让设备与显示的名称对应的方法
                    this.farmnames = FARMNAMES[vm.province][data.farm];
                    var obj = {};
                    var arr = [];
                    var addDate = [];
                    var forSaveFantype = [];
                    if(data.fantype.indexOf(',')>-1){
                        arr = data.fantype.split(',');
                    }else{
                        arr.push(data.fantype)
                    }
                    arr.forEach(function(item) {
                        forSaveFantype.push({name:'fantype',value : item});
                    })
                    //为了获得当全部选择相同时间的时候得出当前月的最后一天
                    addDate=data.endDate.split('-');
                    this.vmStartTime=data.startDate+'-01';
                    this.vmEndTime=data.endDate+"-"+this.getLastDay(addDate[0],addDate[1]);
                    obj = {
                        startDate: data.startDate,
                        endDate: data.endDate,
                        province: data.province,
                        dimension: data.dimension,
                        farm: data.farm,
                        forSaveFantype: forSaveFantype
                    }
                    this.getSeqData(obj);
                },
                //请求完成调用方法为echart传递参数
                initParams: function(data,currentChose){
                    var obj = {};
                    _.forIn(this.farmnames[vm.farmValue], function(value, key) {
                        _.assign(obj,value);
                    });
                    var that = this;
                    that.data=[];
                    that.startTime = new Date(that.vmStartTime);
                    that.startTime = that.startTime.getTime()/1000;
                    that.endTime = new Date(that.vmEndTime);
                    that.endTime = that.endTime.getTime()/1000;
                    if(data){
                        for (var i = 0; i < data.length; i++) {
                            var j = 0;
                            that.categories.forEach(function(item,index){
                                if(item == data[i].taskName){
                                    j = index;
                                }
                            })
                            var opacity = 1;
                            if(!currentChose){
                                opacity = 1;
                            }else{
                                if(currentChose && currentChose == data[i].status){
                                    opacity = 1;
                                }else{
                                    opacity = 0.1;
                                }
                            }
                            that.data.push({
                                name: data[i].taskName,
                                value: [
                                    j,
                                    data[i].startDate,
                                    data[i].endDate,
                                    data[i].endDate-data[i].startDate
                                ],
                                itemStyle: {
                                    normal: {
                                        color: that.peerColor[data[i].status],
                                        opacity : opacity
                                    },
                                    
                                }
                            });
                        }
                    }
                    
                    //控制图标中元素的大小样式
                    this.paramOption();
                    if(this.myChart){
                        this.myChart.dispose();
                    }
                    this.myChart = echarts.init(this.$refs.scatter);
                    this.myChart.setOption(this.option);
                    that.searchLock= false;
                },
                paramOption: function(data){
                    var that = this;
                    this.option = {
                        tooltip: {
                            trigger : 'item',
                            show:true,
                            showDelay: 0,
                            hideDelay: 0,
                            transitionDuration:0, 
                            backgroundColor : '#061934',
                            borderColor : '#00f6ff',
                            borderRadius : 8,
                            borderWidth: 2,
                            padding: 10,    // [5, 10, 15, 20]
                            formatter: function (params) {
                                return '开始时间 : ' + that.timestampToTime(params.value[1],true) + '<br/>' + '结束时间 : ' + that.timestampToTime(params.value[2],true) + '<br/>' +'风机名称 : ' + params.name ;
                            }
                        },
                        grid:{
                            x:70,
                            y:5,
                            x2:40,
                            y2:70,
                            borderWidth:1
                        },
                        xAxis: {
                            min : that.startTime,
                            max : that.endTime,
                            scale: true,
                            axisLabel: {
                                formatter: function (val) {
                                    return that.timestampToTime(val);
                                },
                                textStyle: {
                                    color: '#fff'
                                },
                                // rotate:-20,
                            },
                            axisLine: {
                                lineStyle: {
                                    type: 'solid',
                                    color: '#6286a8',//左边线的颜色
                                    width:'1'//坐标线的宽度
                                }
                            },
                            //去掉刻度线
                            axisTick: {
                                show: false
                            },
                            //x轴上面的线
                            splitLine:{ 
                                show:false
                            },
                        },
                        yAxis: {
                            data: that.categories,
                            axisLabel: {
                                textStyle: {
                                    color: '#fff'
                                },
                                // rotate:-20,
                            },
                            axisLine: {
                                lineStyle: {
                                    type: 'solid',
                                    color: '#6286a8',//左边线的颜色
                                    width:'1'//坐标线的宽度
                                },
                                textStyle:{
                                    fontSize:15,
                                    color:'#fff'
                                }
                            },
                            
                            axisTick: {
                                show: false
                            },
                            splitLine:{ 
                                show:false
                            },
                        },
                        series: [{
                            type: 'custom',
                            renderItem: that.renderItem,
                            itemStyle: {
                                normal: {
                                    opacity: 0.8
                                }
                            },
                            encode: {
                                x: [1, 2],
                                y: 0
                            },
                            data: that.data
                        }]
                        
                    };
                },
                //修改echarts自定义画图规则
                renderItem: function(params, api) {
                    var categoryIndex = api.value(0);
                    var start = api.coord([api.value(1), categoryIndex]);
                    var end = api.coord([api.value(2), categoryIndex]);
                    var height = api.size([0, 1])[1] * 0.6;           
                    return {
                        type: 'rect',
                        shape: echarts.graphic.clipRectByRect({
                            x: start[0],
                            y: start[1] - height / 2,
                            width: end[0] - start[0],
                            height: height
                        }, {
                            x: params.coordSys.x,
                            y: params.coordSys.y,
                            width: params.coordSys.width,
                            height: params.coordSys.height
                        }),
                        style: api.style()
                    };
                },
                //获取序列图数据
                getSeqData: function(obj) {
                    var that = this;
                    that.loading = true;
                    $.ajax({
                        url: "/apps/fault/getSeqData.php",         
                        dataType: "json",   
                        async: true,        
                        type: "post",
                        data: obj, 
                        success: function(data) { //此处data为返回值
                            if(data.error_code){
                                that.$message(
                                    {
                                        showClose: true,
                                        message: '链接错误请求失败!',
                                        type: 'warning',
                                        customClass:'messageClass',
                                        iconClass:'icon-yn-warn'
                                    }
                                )
                                if(that.myChart){
                                    that.myChart.dispose();
                                }
                                that.myChart=null;
                                that.loading = false;
                            }
                            var arr = [];
                            var status = [];
                            var objName = {};
                            if(data){
                                _.forIn(that.farmnames, function(value, key) {
                                    _.assign(objName,value);
                                });
                                data.forEach(function(item){
                                    item.taskName = objName[item.taskName];
                                    arr.push(item.taskName);
                                    status.push(item.status);
                                    item.startDate = new Date(item.startDate).getTime()/1000;
                                    item.endDate = new Date(item.endDate).getTime()/1000;
                                })
                                that.status = _.uniq(status);
                                that.status.forEach(function(item,index){
                                    that.peerColor[item] = that.colorList[index];
                                });
                                that.categories = _.uniq(arr);
                                that.totalData = data;
                                that.initParams(data);
                                that.loading = false;
                                
                            }
                        },
                        error: function() {
                            that.searchLock= false;
                            that.loading = false;
                            console.log('接口错误');
                        }
                    })
                },
                timestampToTime : function(timestamp ,flag) {
                    var date = new Date(timestamp * 1000);//时间戳为10位需*1000,时间戳为13位的话不需乘1000
                    var Y = date.getFullYear() + '-';
                    var M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-';
                    var D = date.getDate() <10 ? '0'+date.getDate() : date.getDate() + ' ';
                    var h = date.getHours() + ':';
                    var m = date.getMinutes() + ':';
                    var s = date.getSeconds();
                    if(flag){
                        return Y+M+D+" "+h+m+s;
                    }else{
                        return Y+M+D;
                    }
                },
                backgroundComputed : function(data) {
                    return {backgroundColor : this.peerColor[data]};
                },
                getLastDay : function(year,month)   {   
                    var new_year = year;  //取当前的年份   
                    var new_month = month++;//取下一个月的第一天,方便计算(最后一天不固定)   
                    if(month>12)      //如果当前大于12月,则年份转到下一年   
                    {   
                    new_month -=12;    //月份减   
                    new_year++;      //年份增   
                    }   
                    var new_date = new Date(new_year,new_month,1);        //取当年当月中的第一天   
                    return (new Date(new_date.getTime()-1000*60*60*24)).getDate();//获取当月最后一天日期   
                },
                barClick : function(item) {
                    this.initParams(this.totalData,item);
                },
                bodyClick :function(item) {
                    this.initParams(this.totalData);
                },
            },
            created: function(){
                
            },
            mounted: function(){
                var that = this;
                this.farmnames = FARMNAMES[vm.province][vm.farmValue];
                this.initParams();
                //一开始默认值请求
                setTimeout(function(){
                    vm.search();
                },10)
                window.addEventListener('resize', function () {
                    if(that.myChart){
                        that.myChart.resize();
                    }
                });
            }
        })
    </script>
    <{/block}>
    

      

    转载于:https://www.cnblogs.com/smallteeth/p/9728616.html

    展开全文
  • 甘特图插件带例子

    2018-11-27 15:23:14
    甘特图插件,里面附带例子,资源丰富。。。。。。。。
  • 强大的破解版甘特图插件,支持选周,月,年等时间。并结合bootstarp。美观
  • 基于vue实现甘特图实现上下拖拽,达到排班的要求,之前困于没有好的方案,在我研究两周后最终实现甘特图的拖拽效果
  • 开源的甘特图插件

    2018-11-27 14:48:54
    基于jQuery 3.2 MIT许可:您可以在任何地方重复使用, JSON导入导出,国际化 、管理任务状态 - >项目工作流程 、管理依赖项、管理任务(资源,角色工作)、服务器同步就绪、完全撤消 - 重做支持、跨浏览器(至少对于...
  • vue echart甘特图

    2019-10-04 23:35:28
    let _this = this; let data = [ { list: [ { colorNum: 0, endTime: "2019-10-10 00:00:00", item: "墙柱", ...
  • vue中展示甘特图

    千次阅读 2020-11-16 17:29:36
    今天分享一篇关于查看任务的甘特图的文章 首先,用的插件是dhtmlx-gantt,官网地址https://docs.dhtmlx.com/gantt/ 官网的Getting started模块是查看甘特图的各种配置 废话不多说,上代码详细说明 子组件模板 <...
  • Vue+dhtmlx前端甘特图

    2020-11-24 15:11:09
    Vue+dhtmlx前端甘特图
  • 基于vue cli3实现甘特图拖拽

    千次阅读 2019-11-14 17:27:31
    基于vue cli3实现甘特图拖拽 因为工作中要用到甘特图,所以我在网上搜索可以用的甘特图,搜索了好多,但是网上搜到大多数都很鸡肋,不能直接使用,最后我在github上搜索到一个相对成熟的甘特图。附上链接...
  • 原型如下,如何简单的实现此甘特图? 谢谢各位了   <p><img alt="" height="457" src="https://img-ask.csdnimg.cn/upload/1623394207953.png" width="1587" /></p>
  • vue怎么制作甘特图——dhtmlx-gantt

    热门讨论 2021-04-06 14:44:47
    </style> 使用这个甘特图插件gantt <template> <div class="container"> <gantt class="left-container" :tasks="tasks"></gantt> </div> </template> <script> import Gantt from '@/components/Gantt.vue';...
  • 偶然间发现这个可以做甘特图,进官网一看发现图挺美观的,而且官方还提供了多种甘特图实例,还集成了不同的前端框架,真是天助我也! FusionCharts官网:https://www.fusioncharts.com/ API:http
  • vue.js中使用甘特图(gantt-elastic)的使用

    千次阅读 热门讨论 2020-08-07 11:17:42
    公司要使用甘特图插件来跟踪任务的进度 ,在使用这个插件的过程中踩了太多的坑了,很多配置都没有文档的 连英文文档都没有,然后就看了源码研究了下具体的配置,具体的配置我都在下面的文章中截图有备注了。...
  • Vue.js项目时间表 Vue.js的类似于甘特图的项目时间表。 安装 npm install @mvsde/vue-project-timeline 基本用法 < script > import ProjectTimeline from ' @mvsde/vue-project-timeline '
  • 关键字:[甘特图,javascript甘特图,打字稿甘特图,项目经理,js甘特图,js计划程序,js时间轴,javascript时间线,javascript计划,js计划程序,javascript日历] 永远记住,留下一颗 :star: 特征 弹性-您几乎...
  • 基于Vue-Gantt-chart组件实现可拖拽甘特图甘特图需求总结甘特图组件评估(含github地址)收费免费评估总结甘特图可拖拽可拉伸拖拽demo实现高级拖拽动画的思路:拉伸demo甘特图最终效果 甘特图需求总结 项目中要用到...
  • 在使用dhtmlxGant(甘特图)时,响应太慢,甚至没有响应,按F12就会显示出来,不按F12就算等多久,都不会显示出来。请问有大佬遇到同样问题吗?都是怎么解决的呢? ----------------------------------更新线------...
  • vue——dhtmlxGantt甘特图API精华总结

    千次阅读 2021-01-11 12:12:18
    //遍历甘特图中的所有选定任务 eachSelectedTask //遍历特定任务或整个甘特图的所有子任务 eachTask //遍历被选中的节点 eachSelectedTask /******导入导出:********/ exportToExcel exportToMSProject ...
  • 甘特图Vue中的应用篇

    千次阅读 2021-01-11 16:44:37
    1、首先安装插件,由于官网上一些功能是收费的,所以我在github上发现一款还不错的插件,并有文档说明(全英) npm i gantt-schedule-timeline-calendar 附上文档地址:...
  • 最近的项目要求甘特图在elementui中实现,在此做出总结。 性能限制,不能传入太多的数据。 需要条件: 时间:计划开始时间、计划结束时间、开始时间、结束时间 最大时间和最小时间。 思维: 渲染表格头、渲染天数、...
  • 甘特图(Gantt chart)又称为横道图、条状图(Bar chart)、生产计划进度图。其通过条状图来显示项目,进度,和其他时间相关的系统进展的内在关系随着时间进展的情况。以提出者亨利·劳伦斯·甘特(Henry Laurence ...
  • 前端时间公司要求制作一个甘特图的组件,本来想用现成的控件,但搜了下都是要money的,或者就是不太好的控件,后来想了下干脆就自己做好了.花了一个多星期的时间做了一个简单的甘特图控件.这个支持日、周、月、季、年的...
  • 目前市面上最有名的几个gantt插件占据江湖了非常久远的时间,它们古老又强大。 但无一例外的是:它们收费或极其难用并且依赖非常古老的技术,其中有些技术现在入行的新手甚至从未听闻。 【jQueryGantt】...
  • 目前市面上最有名的几个gantt插件占据江湖了非常久远的时间,它们古老又强大。 但无一例外的是:它们收费或极其难用并且依赖非常古老的技术,其中有些技术现在入行的新手甚至从未听闻。 【jQueryGantt】【plusgantt...

空空如也

空空如也

1 2 3 4 5 ... 15
收藏数 288
精华内容 115
关键字:

vue甘特图插件

vue 订阅