baozhengrui

导航

dhtmlx - gantt---甘特图

引入依赖 npm install dhtmlx-gantt@7.1.7

实例:

<template>
  <div class="ganttShow">
    <div class="common-query">
      <div class="common-query-demo">
        <span>产品名称</span>
        <el-input placeholder="请输入产品名称" v-model="query.orderName"></el-input>
      </div>
  
      <div class="common-query-demo">
        <span>交货期</span>
        <el-date-picker v-model="query.deliDate" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" unlink-panels></el-date-picker>
      </div>
      <div class="common-query-demo">
        <el-button icon="el-icon-search" @click="queryEdit">查询</el-button>
      </div>
    </div>
    <div class="ganttShow-body">
      <div class="common-btn">
        <span>试算时间:2020-05-29 12:25:30</span>
        <el-button type="primary" @click="HungCommenced">挂起/开工</el-button>
      </div>
      <div class="ganttShow-box" :style="ganttStyle">
        <div id="gantt_here" style="height: 100%"></div>
      </div>
      <div class="ganttShow-foot">
        <div class="ganttShow-foot-desc">
          <img src="@assets/img/normal.png" />
          <span>排程正常</span>
        </div>
        <div class="ganttShow-foot-desc">
          <img src="@assets/img/overtime.png" />
          <span>产生加班</span>
        </div>
        <div class="ganttShow-foot-desc">
          <img src="@assets/img/warring.png" />
          <span>不满足交期</span>
        </div>
        <div class="ganttShow-foot-desc">
          <img src="@assets/img/shelve.png" />
          <span>挂起</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { reactive, toRefs, onMounted, onUnmounted } from 'vue'
import { gantt } from 'dhtmlx-gantt' // 引入模块
import '@gantt/skins/dhtmlxgantt_meadow.css' // 皮肤
import '@gantt/locale/locale_cn' // 本地化
import { ganttShowData } from '@api/pplant/ganttShow'
import { ElMessage } from 'element-plus'

export default {
  name: 'ganttShow',
  setup() {
    // 定义的变量
    const state = reactive({
      query: {
        orderName: '',
        number: '',
        deliDate: ''
      },
      ganttStyle: {
        height: ''
      },
      tableData: [],
      optioms: [],
      tasks: {
        data: []
      }
    })

    // 表格数据请求
    function getGanttShowData() {
      ganttShowData().then(res => {
        state.tasks.data = res.data
        state.optioms = res.options
        Init()
      })
    }

    function Init() {
      // 当task的长度改变时,自动调整图表坐标轴区间用于适配task的长度
      gantt.config.fit_tasks = true
      // 禁止用户拖动条形图来改变位置
      gantt.config.drag_move = false
      // 禁止用户推拽条形图上用来调整进度百分比的小按钮
      gantt.config.show_progress = false
      // 禁止通过拖拽的方式新增任务依赖的线条
      gantt.config.show_links = false
      // 允许用户通过拖拽任务的条形图的两端来改变工期
      gantt.config.drag_resize = false
      // 设置左侧表格的宽度
      gantt.config.grid_width = 300
      // 时间轴列的最小宽度
      gantt.config.min_column_width = 25
      // 时间轴图表中,任务条形图的高度
      gantt.config.bar_height = 10
      // 时间轴图表中,包头部分的高度
      gantt.config.scale_height = 50
      // 时间轴图表中,甘特图的高度
      gantt.config.row_height = 20
      // // 定义弹出框select选择内容
      var opts = state.optioms
      // 定义lightbox弹出框
      gantt.locale.labels.section_cause = '修改原因' // 自定义字段
      gantt.locale.labels.section_remark = '备注' // 自定义字段
      gantt.config.lightbox.sections = [
        {
          name: 'description',
          height: 38,
          map_to: 'text',
          type: 'template'
        },
        {
          name: 'cause',
          height: 28,
          map_to: 'cause',
          type: 'select',
          options: opts
        },
        {
          name: 'remark',
          height: 38,
          map_to: 'remark',
          type: 'textarea',
          focus: true
        },
        {
          name: 'time',
          height: 38,
          type: 'time',
          map_to: 'auto',
          time_format: ['%Y', '%m', '%d', '%H:%i']
        }
      ]
      // 弹框的日期格式处理
      gantt.config.date_format = '%Y-%m-%d %H:%i'
      gantt.config.task_date = '%Y-%m-%d %H:%i'
      // 工期计算的基本单位
      gantt.config.duration_unit = 'minute'
      gantt.config.duration_step = 1
      // 设置x轴日期
      gantt.config.scale_unit = 'month'
      gantt.config.step = 1
      gantt.config.date_scale = '%Y-%m'
      // 设置时间以分钟为单位
      gantt.config.time_step = 1
      // 在时间线上增加一行显示日
      gantt.config.subscales = [
        {
          unit: 'day',
          step: 1,
          date: '%d'
        }
      ]
      // 显示到进度条上的文本为空
      gantt.templates.task_text = function () {
        return null
      }
      // 自定义按钮
      gantt.attachEvent('onGanttReady', function () {
        gantt.config.buttons_left = ['gantt_save_btn']
      })
      gantt.attachEvent('onGanttReady', function () {
        gantt.config.buttons_right = ['gantt_cancel_btn']
      })
      // 初始化列 (自定义的时候需要更改源码匹配自己新增name字段 否则undefined)
      gantt.config.columns = [
        {
          name: 'text', // 自定义字段
          label: '订单名称', // 用于界面展示的名称
          tree: true // 当前列节点是否带图标
        }
      ]
      // 鼠标经过时弹出框提示
      gantt.plugins({
        tooltip: true
      })
      // 设置父任务条形图颜色与子任务区别
      gantt.templates.task_class = function (start, end, item) {
        return item.$level == 0 ? 'gantt_project' : ''
      }
      // 设置父任务ID不可操作
      gantt.attachEvent('onBeforeLightbox', function (id) {
        var task = gantt.getTask(id)
        if (task.progress == 1) {
          return false
        }
        return true
      })
      // 悬浮提示框内容设置
      gantt.templates.tooltip_text = function (start, end, task) {
        // alert(task.start_date)
        // alert(start)
        return (task.text + '<br /><b>开始时间:</b>' + task.start_date + '<br /><b>结束时间:</b>' + task.end_date)
      }
      // 突出周末
      gantt.templates.timeline_cell_class = function (item, date) {
        // debugger
        if (date.getDay() == 0 || date.getDay() == 6) {
          return 'weekend'
        }
      }
      // 显示当天
      gantt.plugins({
        marker: true
      })

      // 显示交货期
      var dateToStr = gantt.date.date_to_str(gantt.config.task_date)
      // js获取时间月份减去1
      var start = new Date(2020, 4, 5, 18, 0, 0) // 实际交货期为5-6
      gantt.addMarker({
        start_date: start,
        css: 'today',
        text: '交货期',
        title: '交货期: ' + dateToStr(start)
      })

      // 显示当天
      var today = new Date()
      gantt.addMarker({
        start_date: today,
        css: 'today',
        text: '今天'
        // title: '今天: ' + dateToStr(today),
      })
      // 设置请求时间格式
      gantt.config.xml_date = '%Y-%m-%d %H:%i'
      // 初始化
      gantt.init('gantt_here')
      // 数据解析
      gantt.parse(state.tasks)
    }

    function HungCommenced() {
      ElMessage.error('暂定!')
    }

    // 查询
    function queryEdit() {
      ElMessage.success('恭喜您,查询成功!')
    }

    function getHeight() {
      state.ganttStyle.height = window.innerHeight - 332 + 'px'
    }

    // 页面加载时调用函数
    onMounted(() => {
      // 请求表格数据
      getGanttShowData()
      // 注册监听器
      window.addEventListener('resize', getHeight)
      // 调用函数
      getHeight()
    })

    onUnmounted(() => {
      // 注销监听器
      window.removeEventListener('resize', getHeight)
    })

    return {
      ...toRefs(state),
      HungCommenced,
      queryEdit
    }
  }
}
</script>

<style lang='scss'>
.ganttShow {
  width: 100%;
  height:100%;

  .ganttShow-body {
    height: calc(100% - 120px);
    margin-top: 20px;
    box-shadow: $box-shadow;
    background: #fff;
    padding: 20px;

    .ganttShow-box{
      margin-top:20px;
    }

    .ganttShow-foot{
      margin-top:20px;
      display: flex;

      .ganttShow-foot-desc{
        margin:0 20px;

        span{
          margin-left:20px;
        }
      }

      .ganttShow-foot-desc:first-child{
        margin-left:0;
      }
    }
  }
}
</style>



在 Vue 中使用 dhtmlxGantt 组件时,gantt.parse中各个参数代表的意思是什么

gantt.parse() 方法是用于将数据解析为 Gantt 图表的方法。它接受一个包含任务和链接数据的对象作为参数。该对象包含以下属性:
data: 任务数据数组,包含每个任务的信息,例如 id、text、start_date、duration 等等。
links: 链接数据数组,包含每个链接的信息,例如 id、source、target 等等。
key: 任务数据对象中唯一标识每个任务的属性名称,默认为 "id"。
parent: 任务数据对象中用于标识父任务的属性名称,默认为 "parent".
open_tree_initially: 布尔值,如果设置为 true,则所有任务默认展开。
preserve_links: 布尔值,如果设置为 true,则链接信息中的任务不存在时也会保留链接。
preserve_tasks: 布尔值,如果设置为 true,则链接信息中的任务不存在时也会保留任务。

例如,可以使用以下代码将数据解析为 Gantt 图表:

const data = [
  { id: 1, text: "Task 1", start_date: "2023-03-15", duration: 3,color:'#c40000' },
  { id: 2, text: "Task 2", start_date: "2023-03-18", duration: 2, parent: 1,color:'#c40000' },
];
/*
gantt.parse 方法中的 data 参数是一个包含任务信息的数组。每个任务都包含多个字段,下面是一些常用的字段及其作用:
id: 任务的唯一标识符。
text: 任务的名称。
start_date: 任务的开始日期,可以是一个字符串或者一个 Date 对象。
end_date: 任务的结束日期,可以是一个字符串或者一个 Date 对象。
duration: 任务的持续时间,以天为单位。如果 end_date 和 duration 都提供了,duration 会被忽略。
progress: 任务的进度,以百分比表示。
parent: 父任务的 id,如果当前任务是顶级任务,则该字段为 0。
open: 是否展开当前任务的子任务。如果不提供,默认为 true。
state: 用于设置任务的状态。状态可以是任何自定义值,例如 "in progress"、"completed"、"cancelled" 等等。
color: 用于甘特图改时间段的颜色
在Gantt 图中,任务的状态可以通过任务条颜色、边框、文本样式等 visulization 属性进行自定义渲染,以便用户更直观地了解任务状态的变化。可以在 Gantt 文档中的 Visualization 属性部分了解有关自定义任务状态可视化的更多信息。
除了上面列出的常用字段之外,还有很多其他可选字段,例如 color、link、type 等,可以根据实际需求来添加。
*/

const links = [
  { id: 1, source: 1, target: 2, type: "0" },
];

gantt.parse({
  data: data,
  links: links,
});
//其中,data 数组包含两个任务,links 数组包含一个链接,最后将这些数据传递给 gantt.parse() 方法进行解析,即可在 Gantt 图表中显示这些任务和链接。

2.在月刻度下需要从1号开始显示到月底最后一天应该怎么显示,直接上代码

import { gantt } from "dhtmlx-gantt"; // 引入模块
import { ref } from "vue";
import dayjs from "dayjs";
import { WorkGantt } from "@/api/information-overview/types";

function adjustColor(color: string, depth: number, alpha: number) {
  // 判断颜色格式
  const isRgb = color.length === 3 || color.length === 4;
  const isHex = /^#[0-9a-fA-F]{6}$/.test(color);

  if (!isRgb && !isHex) {
    throw new Error(
      "Invalid color format. Accepted formats: RGB (e.g., [255, 0, 0]) or Hex (e.g., #ff0000)"
    );
  }

  // 将RGB或十六进制颜色转为RGBA格式
  let rgbaColor: any;
  if (isRgb) {
    rgbaColor = [...color, alpha];
  } else if (isHex) {
    const rgbColor = hexToRgb(color) as number[];
    rgbaColor = [...rgbColor, alpha];
  }

  // 根据深浅值调整RGBA值
  rgbaColor = adjustColorValue(rgbaColor, depth);

  return `rgba(${rgbaColor[0]},${rgbaColor[1]},${rgbaColor[2]},${rgbaColor[3]})`;
}

// 十六进制转RGB
function hexToRgb(hex: string) {
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result
    ? [
        parseInt(result[1], 16),
        parseInt(result[2], 16),
        parseInt(result[3], 16),
      ]
    : null;
}

// 调整颜色深浅值和透明度
function adjustColorValue(rgba: number[], depth: number) {
  return [
    Math.round(rgba[0] + depth) > 255 ? 255 : Math.round(rgba[0] + depth),
    Math.round(rgba[1] + depth) > 255 ? 255 : Math.round(rgba[1] + depth),
    Math.round(rgba[2] + depth) > 255 ? 255 : Math.round(rgba[2] + depth),
    rgba[3], // 保持透明度不变
  ];
}

const ganttRef = ref();



const init=()=>{


  gantt.config.date_format = "%Y/%m/%d"; //整体格式
  gantt.config.duration_unit = "month"; //工期计算的基本单位
  gantt.config.scale_unit = "month"; //列间隔

// 表头数据
gantt.config.columns = [{
  name:'text',  //表头的字段名
  label:'项目',  //表头显示数据名称
   tree:true,   //是否以树形结构展示
   width:align  // 是否居中
}]

// 提示框内容
 gantt.templates.tooltip_text = function (start, end, task) {
    return `
    <h3>关键节点详情</h3>
    <div class="pop-message"><span>关键节点</span><span>${
      task.keyNode ? task.keyNode : "暂无"
    }</span></div>
    <div class="pop-message"><span>签收人</span><span>${
      task.receiver ? task.receiver : "暂无"
    }</span></div>
    <div class="pop-message"><span>节点数量</span><span>${
      task.quantity
    }</span></div>
    <div class="pop-message"><span>完成数量</span><span>${
      task.progressValue
    }</span></div>
    <div class="pop-message"><span>复盘认识</span><span>${
      task.reflectionOnKnowledge ? task.reflectionOnKnowledge : "暂无"
    }</span></div>
    <div class="pop-message"><span>复盘问题</span><span>${
      task.reflectionOnProblems ? task.reflectionOnProblems : "暂无"
    }</span></div>
    <div class="pop-message"><span>复盘总结</span><span>${
      task.reflectionOnCountermeasures
        ? task.reflectionOnCountermeasures
        : "暂无"
    }</span></div>
    `;
  };

gantt.i18n.setLocale("cn"); //中文
  gantt.config.autosize = true; //自适应尺寸
  gantt.config.autofit = true; // 表格列宽自适应
  gantt.config.open_tree_initially = true; // 默认是否展开树结构
  //只读模式
  gantt.config.readonly = true;
  // 显示网格
  gantt.config.show_grid = true;
gantt.config.scale_unit = "month";  // 设置 scale_unit 属性为 month,以显示月刻度

gantt.config.step = 1;  // 设置 step 属性为 1,以每个月显示一个刻度

gantt.config.date_scale = "%Y-%m-%d";  // 设置 date_scale 属性为 %Y-%m-%d,以显示年月日格式的刻度

gantt.config.scale_date = gantt.date.monthStart;  // 设置 scale_date 属性为 gantt.date.monthStart,以从每个月的第一天开始显示刻度。

gantt.config.subscales = [  // 设置 subscale 属性为一个包含两个刻度的对象,分别为 day 和 week。
  { unit: "day", step: 1, date: "%d" },  //  只显示天
  { unit: "week", step: 1, date: "#%W" },  //按周显示
  { unit: "month", step: 1, date: "%Y-%M" },   // 按月显示
  { unit: "year", step: 1, date: "%Y" },  // 按年显示
];

// 跳过节假日
gantt.config.work_time = true
gantt.config.currect_work_time = true

  // 任务移动后的回调事件
  gantt.attachEvent("onAfterTaskMove", (id, parent, tindex) => {
      newUpdateSortCode(id, parent, tindex);
  });

// 数据解析
gantt.parse({
  data: data,
  links: links,
});

gantt.config.start_date = new Date(startDate);
    gantt.config.end_date = new Date(endDate);
    gantt.init(ganttRef.value); // 初始化
    gantt.parse(data);  // 解析数据
gantt.clearAll(); // 清除
gantt.refreshData(); // 刷新


}

posted on 2024-09-04 17:14  芮艺  阅读(93)  评论(0编辑  收藏  举报