React 中如何使用 dhtmlxGantt 甘特图

1,907 阅读3分钟

React 中如何使用 dhtmlxGantt 甘特图 function语法

申请.webp

www.evget.com/article/202…

官方文档 --建议翻墙食用

dhtmlx.com/docs/produc…

docs.dhtmlx.com/gantt/api__…

常用api

www.cnblogs.com/lynn-600/p/…

一列多行:级添加 render: 'split'

效果图

image.png

代码直接cv食用更佳

步骤 1

import { Button, Dropdown, Menu } from 'antd'
import React, { useEffect, useState } from 'react'

import Gantt from './Gantt/index'//步骤二的代码
function DHX() {
  /**
   * Year 年
   * Quarter 月
   * Days 日
   * Hours 时
   *
   */
  const sum = [
    { name: '年', id: 'Year' },
    { name: '月', id: 'Quarter' },
    { name: '日', id: 'Days' },
    { name: '时', id: 'Hours' }
  ]
  // const currentZoom = 'Hours'
  const [currentZoom, setCurrentZoom] = useState<any>('Days') //缩放的状态

  const [data, setData] = useState<any>({ data: [], links: [] }) //初始值为空

  const [messages, setMessages] = useState<any>([
    { message: 'link create: 1648541366992  ( source: 1, target: 2 )' }
  ])
  useEffect(() => {
    api()
  }, [])
  const api = () => {
    const list: any = {
      /**
       * links
       *source
       * target
       * type 1首0尾
       * parent: 1 属于谁
       */

      data: [
        //给父节点设置一个单独的状态 用于判断不可移动
        {
          id: 1,
          text: '路飞一号', //名称
          start_date: '2020-04-08', //日期
          duration: 6, //天数
          progress: 1, //控制完成百分比 范围0-1
          color: 'red' //控制颜色
        },
        {
          id: '1|0',
          text: '路飞二号',
          start_date: '2020-04-08',
          duration: 2,
          progress: 0.6,
          parent: 1,
          color: '#d9363e', //控制颜色
          render: 'split' //添加同一行
        },
        {
          id: '1|1',
          text: '路飞二号的子1',
          start_date: '2020-04-8',
          duration: 2,
          progress: 0.6,
          parent: '1|0'
        },
        {
          id: '1|2',
          text: '路飞二号的子2',
          start_date: '2020-04-10',
          duration: 2,
          progress: 0.6,
          parent: '1|0'
        },
        {
          id: '1|3',
          text: '路飞二号的子3',
          start_date: '2020-04-12',
          duration: 2,
          progress: 0.6,
          parent: '1|0'
        },
        {
          id: 3,
          text: '路飞三号',
          start_date: '2020-04-10',
          duration: 3,
          progress: 0.6,
          parent: 1
        },
        {
          id: 4,
          text: '路飞四号',
          start_date: '2020-04-12',
          duration: 3,
          progress: 0.6
        }
      ],
      /**
       * id 唯一
       * { id: 1, source: 2, target: 13, type: 0 },
       * 2的尾部连接13
       */

      links: [
        { id: 1, source: 1, target: 2, type: 0 },
        { id: 3, source: 2, target: 3, type: 0 }
      ]
    }
    setData(list)
  }

  const addMessage = (message: any) => {
    const maxLogLength = 5
    const newMessage = { message }
    const messagesDome = [newMessage, ...messages]
    if (messagesDome.length > maxLogLength) {
      messagesDome.length = maxLogLength
    }
    setMessages(messagesDome)
  }
  //划过事件
  const logDataUpdate = (type: any, action: any, item: any, id: any) => {
    console.log('item', item)
    // api()
  }
  const choose = (type: any) => {
    setCurrentZoom(type)
  }

  const menu = (
    <Menu>
      {sum.map((item) => (
        <>
          <Menu.Item>
            <div onClick={() => choose(item.id)} key={item.id}>
              {item.name}
            </div>
          </Menu.Item>
        </>
      ))}
    </Menu>
  )
  return (
    <div>
      <div>
        <div>
          <Dropdown overlay={menu} placement="topRight" arrow>
            <Button>缩放</Button>
          </Dropdown>
        </div>
        <div className="gantt-container">
          <Gantt
            tasks={data}
            zoom={currentZoom}
            onDataUpdated={logDataUpdate}
          />
        </div>
      </div>
    </div>
  )
}

export default DHX

步骤2

import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'

import { gantt } from 'dhtmlx-gantt'
import React, { Component, useEffect, useState } from 'react'

function Gantt(props: any) {
  const { zoom, tasks, onDataUpdated } = props
  // const [type, setType] = useState(true)

  const chartDom = document.getElementById('main') //获取id

  // 参数设置
  const initZoom = () => {
    gantt.i18n.setLocale('cn') //设置中文
    // gantt.config.readonly = true//只读
    gantt.config.order_branch = true // 左侧可以拖动
    gantt.config.sort = true //左侧点击表头排序
    // gantt.config.drag_move = true //是否可以移动
    // gantt.config.drag_progress = false //拖放进度
    gantt.config.drag_resize = true //控制大小
    gantt.ext.zoom.init({
      levels: [
        {
          name: 'Hours',
          scale_height: 60,
          min_column_width: 30,
          scales: [
            { unit: 'day', step: 1, format: '%d %M  ' },
            { unit: 'hour', step: 1, format: '%H' }
          ]
        },
        {
          name: 'Days',
          scale_height: 60,
          min_column_width: 70,
          scales: [
            // { unit: 'week', step: 1, format: '#%W' },
            { unit: 'day', step: 1, format: ' %M%d' }
          ]
        },
        {
          name: 'Months',
          scale_height: 60,
          min_column_width: 70,
          scales: [
            { unit: 'month', step: 1, format: '%F' },
            { unit: 'week', step: 1, format: '#%W' }
          ]
        }
      ]
    })

    // 可以通过此控制 是否可以拖动
    gantt.attachEvent(
      'onBeforeTaskDrag',
      function (id: any, mode: any, e: any) {
        const task = gantt.getTask(id)
        // console.log('onBeforeTaskDrag', id, mode, e, task)
        console.log('task', task)
        if (task.id === 1) {
          return false
        } else {
          return true
        }
      }
    )
    //测试---------------------
    gantt.config.fit_tasks = false
    // 双击task时,弹出lightbox弹出框
    gantt.attachEvent('onEmptyClick', function (e: any) {
      console.log('我点击了空白')
    })
    //缩放
    const zoomConfig = {
      levels: [
        {
          name: 'Hours', //时
          scale_height: 60,
          min_column_width: 30,
          scales: [
            { unit: 'day', step: 1, format: '%M %d ' },
            { unit: 'hour', step: 1, format: '%H' }
          ]
        },
        {
          name: 'Days', //日
          scale_height: 27,
          min_column_width: 100,
          scales: [{ unit: 'day', step: 1, format: ' %M %d' }]
        },
        {
          name: 'Quarter', //月
          height: 100,
          min_column_width: 90,
          scales: [{ unit: 'month', step: 1, format: '%M' }]
        },
        {
          name: 'Year', //年
          scale_height: 50,
          min_column_width: 30,
          scales: [{ unit: 'year', step: 1, format: '%Y' }]
        }
      ]
    }

    gantt.ext.zoom.init(zoomConfig)
    //测试结束---------------------
  }

  const setZoom = (value: any) => {
    if (!gantt.$initialized) {
      initZoom()
    }
    //缩放
    gantt.ext.zoom.setLevel(value)
  }
  useEffect(() => {
    setZoom(zoom)
  }, [zoom])
  useEffect(() => {
    if (tasks) {
      componentDidMount(tasks)
    }
  }, [tasks])

  const initGanttDataProcessor = () => {
    gantt.createDataProcessor((type: any, action: any, item: any, id: any) => {
      return new Promise<void>((resolve, reject) => {
        if (onDataUpdated) {
          onDataUpdated(type, action, item, id)
        }
        return resolve()
      })
    })
  }
  const componentDidMount = (list: any) => {
    gantt.config.date_format = '%Y-%m-%d %H:%i'
    gantt.init(chartDom) //根据 id
    initGanttDataProcessor()
    gantt.parse(list) //渲染数据
  }
  return <div id="main" style={{ width: '100%', height: '100%' }}></div>
}

export default Gantt