index.js 5.15 KB
import React, { Component } from 'react';
import { gantt } from 'dhtmlx-gantt';
import { DoubleRightOutlined } from '@ant-design/icons';
import 'dhtmlx-gantt/codebase/dhtmlxgantt.css';
import './Gantt.css';

/* eslint-disable */
class Gantt extends Component {

  state = { expanded: true };
  tableHeight = 60;

  componentDidMount() {
    gantt.plugins({
      tooltip: true, // 鼠标划过任务是否显示明细
      // auto_scheduling: true,//根据任务之间的关系自动安排任务
      // multiselect: true, //为任务激活多任务选择
    });
    gantt.config.xml_date = '%Y-%m-%d %H:%i'; /* 时间格式 年月日 时分 */
    gantt.config.reorder_grid_columns = true; /* 左侧列可拖动 */
    gantt.config.grid_elastic_columns = true;
    gantt.config.drag_mode = { ignore: 'ignore'};
    gantt.config.scale_height = this.tableHeight;
    gantt.i18n.setLocale('cn');
    // gantt.config.readonly = true;// 只读模式的甘特图
    const { tasks } = this.props;
    this.setTemplate();
    gantt.init(this.ganttContainer);
    this.initGanttDataProcessor();
    gantt.parse(tasks);
  }


  shouldComponentUpdate(nextProps, nextState) {
    // const { tasks } = nextProps;
    // return tasks !== undefined;
    return this.props.zoom !== nextProps.zoom || this.state.expanded !== nextState.expanded;
  }
  componentDidUpdate() {
    gantt.clearAll();
    const { tasks } = this.props;
    this.setTemplate();
    gantt.init(this.ganttContainer);
    this.initGanttDataProcessor();
    gantt.parse(tasks);
  }
  componentWillUnmount() {
    if (this.dataProcessor) {
      this.dataProcessor.destructor();
      this.dataProcessor = null;
    }
  }
  setZoom = (value) => {
    const scale = value.scale !== undefined ? value.scale : 'Minutes';
    const step = value.step !== undefined ? value.step : 10;
    switch (scale) {
      case 'Minutes':
        gantt.config.duration_unit = 'minute';
        gantt.config.scale_unit = 'day';
        gantt.config.date_scale = '%Y-%m-%d';
        gantt.setWorkTime({ hours: ['00:30-03:30'] });
        gantt.config.scale_height = 60;
        gantt.config.min_column_width = 40;
        gantt.config.subscales = [
          { unit: 'minute', step, date: '%H:%i' },
        ];
        break;
      case 'Hours':
        gantt.config.scale_unit = 'day';
        gantt.config.date_scale = '%M %d';

        gantt.config.scale_height = 60;
        gantt.config.min_column_width = 30;
        gantt.config.subscales = [
          { unit: 'hour', step, date: '%H' },
        ];
        break;
      case 'Days':
        gantt.config.min_column_width = 70;
        gantt.config.scale_unit = 'week';
        gantt.config.date_scale = '%Y-%m-%d';
        gantt.config.subscales = [
          { unit: 'day', step, date: '%M %d' },
        ];
        gantt.config.scale_height = 60;
        break;
      case 'Months':
        gantt.config.min_column_width = 70;
        gantt.config.scale_unit = 'month';
        gantt.config.date_scale = '%F';
        gantt.config.scale_height = 60;
        gantt.config.subscales = [
          { unit: 'week', step, date: '#%W' },
        ];
        break;
      default:
        break;
    }
  }
  initGanttDataProcessor =() => {
    // eslint-disable-next-line prefer-destructuring
    const onDataUpdated = this.props.onDataUpdated;
    if (this.dataProcessor) {
      this.dataProcessor.destructor();
      this.dataProcessor = null;
    }
    this.dataProcessor = gantt.createDataProcessor((type, action, item, id) => {
      return new Promise((resolve) => {
        if (onDataUpdated) {
          onDataUpdated(type, action, item, id);
        }

        // if onDataUpdated changes returns a permanent id of the created item, you can return it from here so dhtmlxGantt could apply it
        // resolve({id: databaseId});
        return resolve();
      });
    });
  }

  setTemplate = () => {
    const { tasks } = this.props;
    if (Array.isArray(tasks?.columns)) {
      gantt.config.columns = tasks?.columns;
    }
    gantt.config.show_grid = this.state.expanded;
    gantt.templates.tooltip_text = function (start, end, task) {
      return (
        '<b>标题:</b> ' +
        task.text +
        '<br/><span>开始:</span> ' +
        gantt.templates.tooltip_date_format(start) +
        '<br/><span>结束:</span> ' +
        gantt.templates.tooltip_date_format(end) +
        '<br/><span>进度:</span> ' +
        Math.round(task.progress * 100) +
        '%'
      );
    };
  }

  render() {
    const { zoom } = this.props;
    this.setZoom(zoom);
    return (
      <div style={{ position: 'relative', height: '100%' }}>
        <DoubleRightOutlined
          style={{
            position: 'absolute',
            zIndex: 1,
            top: this.state.expanded ? this.tableHeight / 2 : this.tableHeight / 4,
            transform: 'translate(50%, -50%)',
            opacity: 0.5,
          }}
          rotate={this.state.expanded ? 180 : 0}
          onClick={() => {
            this.setState({ expanded: !this.state.expanded });
          }}
        />
        <div
          ref={(input) => { this.ganttContainer = input; }}
          style={{ width: '100%', height: '100%' }}
        />
      </div>
    );
  }
}
export default Gantt;