由于在做公司项目时,车间要对生产的项目计划进行编制,根据自身需求我了解相关技术和自身业务需求,最终选择DHTMLX的gantt组件来实现计划的编排和修改等。

我们公司项目采用VUE3技术,前端实现计划的编排,修改等功能;创建计划节点可以上移、下移、复制、前进、后退等操作;最后效果

1、DHTMLX相关资料学习

    1.1  api学习,里面api挺多的,支持搜索大家可以根据自己的需求进行学习            

         Gantt API Gantt Docs   

    1.2   官方给的一些demo,大家可以学习参考

         DHTMLX - Gantt. Advanced demo

2、具体实现逻辑

   首先根据api配置gantt图展示的属性,下面主要是我用到的配置项:

  const getGanttInfo = () => {
    // 清空之前的配置
    gantt.clearAll();
    // 配置基本属性
    gantt.config.readonly = true// 是否只读
    gantt.attachEvent("onTaskDblClick", function (id, e) { return false }); // 禁止点击进行弹窗
    gantt.templates.grid_row_class = function (start, end, task) {
      return gantt.hasChild(task.id) ? "gantt_parent_row" : "";
    };
    gantt.attachEvent("onGanttScroll", function (left, top) {
      if (top === 0) {
        return false
      } else {
        scrollTop.value = top
      }
    });
    gantt.attachEvent("onTaskOpened", function (id) {
      openTasks.value.push(id)
    });
    gantt.attachEvent("onTaskClosed", function (id) {
      openTasks.value.map((item, index) => {
        if (item == id) {
          openTasks.value.splice(index, 1)
        }
      })
    });
    gantt.i18n.setLocale('cn'); // 设置 Gantt 图的界面语言为中文
    gantt.config.show_grid = true; // 显示 Gantt 图中的网格线
    gantt.config.grid_width = 900;
    gantt.config.show_unscheduled = false;
    gantt.config.grid_elastic_columns = true;
    gantt.config.details_on_create = false; // 点击+时关闭灯箱弹窗
    gantt.config.fit_tasks = true; // 自动延长时间刻度
    // 配置外部渲染,使用onrender时的渲染方式
    gantt.config.external_render = {
      isElement: (element) => {
        return isValidVNode(element);
      },
      renderElement: (element, container) => {
        render(element, container);
      },
    };
  
    // 配置刻度单位
    setUnit(props.editType); // 甘特图刻度配置
    gantt.config.duration_unit = props.editType;
    if (props.editType === 'day') {
      gantt.config.time_step = 10; // 时间轴上的每个刻度间隔为 10 天
    }
    gantt.config.step = 1; // 设置步长为 1
    gantt.config.scale_height = 28 * 3; // 甘特图的时间刻度高度
    gantt.config.min_column_width = 16;
    gantt.config.duration_step = 1; // 任务持续时间步长
    gantt.config.redo = true; // 重做功能
    gantt.config.undo = true; // 启用撤销功能
    gantt.config.order_branch = 'marker'; // 左侧树型结构调整时,只允许将任务拖放到某个父节点下
    gantt.config.order_branch_free = true; // 左侧树型结构调整时,可以任意拖动任务到任意节点下
    gantt.config.auto_scheduling = true; // 控制任务是否自动重新安排
    gantt.config.show_errors = false; // 发生异常时,不允许弹出警告到 UI 界面
  
    // 初始化扩展设置
    setGanttColumn() // 配置甘特图右侧表格
    addTaskType(); // 添加任务类型
    // 插件配置
    gantt.plugins({
      tooltip: true, // 设置工具提示
      quick_info: false, // 快速信息框进行隐藏
      export_api: true, // 导出 API
      undo: true, // 启用撤销功能
      marker: true, // 标记
      auto_scheduling: true, // 控制任务是否自动重新安排
    });
  
    // 添加今天的标记
    addTodayMarker();
    addProjectStartMarker()
  
    // 展开或折叠树形结构
    if (collapse.value) {
      expandAll();
    } else {
      collapseAll();
    }
    // 初始化甘特图
    gantt.init(ganttRef.value);
    gantt.parse(props.taskData);
  };

   2、左侧表格配置像设置,我的需求是表格里的名称、开始时间、结束时间、工期等都可以编辑

// 甘特图列配置
  const setGanttColumn = () => {
    customEditor()
    const textEditor = { type: 'text', map_to: 'text' }
    const startDateEditor = { type: 'date', map_to: 'start_date' }
    const endDateEditor = { type: 'date', map_to: 'end_date' }
    const adjustFinishTimeEditor = { type: 'date', map_to: 'adjustFinishTime' }
    const numberEditor = { type: 'number', map_to: 'progress', min: 0, max: 100 }
    const durationEditor = { type: 'number', map_to: 'duration', min: 1 }
    const predecessorEditor = { type: "predecessor", map_to: "auto" }
    const statueEditor = { type: "status_editor", map_to: "status" }
    gantt.config.columns = [  // 配置表头
      { align: 'center', name: 'add', label: '', width: 30 },
      {
        align: 'center',
        name: 'buttons',
        label: '选择',
        width: 35,
        onrender: (task: any, node: HTMLInputElement) => {
          let input = document.createElement('INPUT');
          input.setAttribute('type', 'checkbox');
          input.setAttribute('style', 'height:35px;width: 20px');
          input.setAttribute('id', 'checkbox' + (task.type !== undefined ? task.type : '') + task.id);
          const findIndex = checkList.value.findIndex((c: String) => c + '' === task.id + '');
          if (findIndex > -1) {
            input.checked = true
          }
          node.firstElementChild?.appendChild(input);
          input.onclick = handleCheckboxChange;
          return node;
        },
      },
      {
        align: 'center',
        name: 'index',
        label: '序号',
        width: 45,
        // resize: true,
        template(task) {
          // return gantt.getGlobalTaskIndex(task.id) + 1;
          return gantt.getWBSCode(gantt.getTask(task.id))
        },
      },
      {
        name: "text", label: "任务名称", align: "left", tree: true, width: 400, editor: textEditor,
        // template(task) {
        //   return "<div :title=" + task.text + "><span title='322323232332'></span>" + task.text !== undefined ? task.text : '新任务' + "</div>"
        // },
        onrender: (item, node) => {
          node.setAttribute("title", item.text);
          return node;
        }
      },
      {
        name: "start_date", label: "预计开始时间", align: "center", width: 250, editor: startDateEditor
      },
      { name: "end_date", label: "预计完成时间", align: "center", width: 250, editor: endDateEditor },
      { name: "adjustFinishTime", label: "调整完成时间", align: "center", width: 250, editor: adjustFinishTimeEditor },
      {
        align: 'center',
        name: 'duration',
        label: '工期',
        width: 90,
        editor: durationEditor
      },
      {
        align: 'center',
        name: 'sno',
        label: '前置任务',
        width: 90,
        editor: predecessorEditor,
        template: function (task) {
          return getPredecessor(task)
        },
      },
      {
        name: "remark", label: "备注", align: "center"
      },
      {
        name: "status", label: `状态`, align: "center", editor:statueEditor
      },
    ];
  }

其他具体操作,感兴趣的可以查看项目源码,下面是源码地址

项目源码:GitCode - 全球开发者的开源社区,开源代码托管平台

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐