在 Vue 2中使用 dhtmlxGantt 7.1.13组件,并解决使用时遇到的问题汇总.“dhtmlx-gantt“: “^7.1.13“,

news2025/7/22 8:45:12

一、最终实现的结果gif展示

二、开发步骤简介

1、vue中引用甘特图包dhtmlx-gantt

// 可根据项目版本载入适配的版本
npm install dhtmlx-gantt@7.1.13

2、vue文件中引入

<script>
import { gantt } from 'dhtmlx-gantt/codebase/dhtmlxgantt.js'
import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'
<script/>

3、html部分

<template>
 <div class="gantt-content"  style="width:100%;height: 100%;">
          <div ref="ganttContainer" style="width:100%;height: 100%;"></div>
    </div>
</template>

4、js部分

  mounted () {
    // 初始化甘特图  注意:保证先初始化,在加载数据,以防万一可以在此基础上自行修改为异步
    this.initGantt()
// 初始化数据
    this.loadData()
  },
  watch: {
    '$route.query.id': {
      handler (newId) {
        if (newId) {
          this.loadData('clearAll')
        }
      },
      immediate: true // 立即执行以处理初始加载
    }
  },
  methods: {
    async loadData (type) {
      this.spinning = true
      if (type === 'clearAll') { gantt.clearAll() } // 避免来回切换页面更改数据时甘特图数据展示混乱
      axiosxxx().then(res => {
        if (rres.code === 200) {
          // 处理任务阶段数据,甘特图回显
          let formattedGanttData = []
          formattedGanttData = res.data.progressItems.map(task => ({
            id: task.id,
            text: task.progressName, // 映射任务名称字段
            start_date: this.formatDate(task.startTime), // 转换为gantt标准字段
            parent: task.parentId,
            open: task.level === 1 ? true : undefined,
            level: task.level,
            duration: task.duration,
            status: task.status
          }))
          gantt.parse({ data: formattedGanttData })
          gantt.render() // 强制重绘
        } else {
          this.$message.error(res.msg)
        }
        this.spinning = false
      }).catch(err => {
        this.$message.error(err.msg)
        this.spinning = false
      })
    },
    // 处理时间格式
    formatDate (dateStr) {
      // 根据你的接口日期格式进行调整-gantt图时间格式要求固定
      let [year, month, day] = dateStr.split('-')
      return new Date(year, month - 1, day) // 月份减1,因为月份是从0开始的
    },
    initGantt () {
      // // 初始化容器
      gantt.init(this.$refs.ganttContainer)
      // 禁用所有交互
      gantt.config.editable = false
      gantt.config.drag_move = gantt.config.drag_resize = false
      gantt.config.select_task = false
      // 禁用编辑功能
      gantt.config.readonly = true
      gantt.config.drag_move = false
      gantt.config.drag_resize = false
      gantt.config.grid_editable = false
      // 隐藏操作栏配置
      gantt.config.tree_actions = true // 隐藏展开/折叠图标
      gantt.config.tree_line = false // 隐藏层级连线
      gantt.config.row_height = 30 // 调整行高适应多行内容
      // gantt.config.min_column_width = 120 // 防止列宽过小
      // 是否显示左侧树表格
      gantt.config.show_grid = true
      // 格式化日期-汉化
      gantt.locale.date = {
        month_full: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
        month_short: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
        day_full: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
        day_short: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
      }
      gantt.locale.labels = {
        dhx_cal_today_button: '今天',
        day_tab: '日',
        week_tab: '周',
        month_tab: '月',
        new_event: '新建日程',
        icon_save: '保存',
        icon_cancel: '关闭',
        icon_details: '详细',
        icon_edit: '编辑',
        icon_delete: '删除',
        confirm_closing: '请确认是否撤销修改!', // Your changes will be lost, are your sure?
        confirm_deleting: '是否删除计划?',
        section_description: '描述:',
        section_time: '时间范围:',
        section_type: '类型:',
        section_text: '计划名称:',
        section_test: '测试:',
        section_projectClass: '项目类型:',
        taskProjectType_0: '项目任务',
        taskProjectType_1: '普通任务',
        section_head: '负责人:',
        section_priority: '优先级:',
        taskProgress: '任务状态',
        taskProgress_0: '未开始',
        taskProgress_1: '进行中',
        taskProgress_2: '已完成',
        taskProgress_3: '已延期',
        taskProgress_4: '搁置中',
        section_template: 'Details',
        /* grid columns */
        column_text: '计划名称',
        column_start_date: '开始时间',
        column_duration: '持续时间',
        column_add: '',
        column_priority: '难度',
        /* link confirmation */
        link: '关联',
        confirm_link_deleting: '将被删除',
        message_ok: '确定',
        message_cancel: '取消',
        link_start: ' (开始)',
        link_end: ' (结束)',
        type_task: '任务',
        type_project: '项目',
        type_milestone: '里程碑',
        minutes: '分钟',
        hours: '小时',
        days: '天',
        weeks: '周',
        months: '月',
        years: '年'
      }
      // 自定义左侧列配置
      gantt.config.columns = [
        { name: 'text',
          label: '任务名称',
          width: '*',
          tree: true,
          // 插入template,title解决字段显示不全的问题
          template: (task) => `
            <div title="${task.text}">
              ${task.text}
            </div>
          `
        },
        { name: 'start_date', label: '开始时间', align: 'center', width: 100 },
        { name: 'duration', label: '持续天数', align: 'center', width: 70 }
      ]
      // 任务条文本模板
      gantt.templates.task_text = (start, end, task) => {
        const cleanText = task.text
          .replace(/</g, '&lt;')
          .replace(/>/g, '&gt;')
          .replace(/"/g, '&quot;')
        return `
          <div class="gantt-task-title" title="${cleanText}">
            ${task.text}
          </div>
        `
      }
      // 自定义行样式(关键修改部分)
      gantt.templates.task_row_class = function (start, end, task) {
        if (task.level === 1) {
          return 'custom-gantt-level_1_row'
        }
        return ''
      }
      // 自定义任务条颜色模板(关键代码)
      gantt.templates.task_class = function (start, end, task) {
        // 调试输出(关键)
        // console.log(`[DEBUG] Task ${task.id}:`, {
        //   level: task.level,
        //   status: task.status,
        //   hasLevel: task.hasOwnProperty('level'),
        //   hasStatus: task.hasOwnProperty('status')
        // })
        switch (true) {
          case (task.level === 1):
            return 'custom-gantt-level_1_bar'
          case (task.level === 2 && task.status === 3):
            return 'custom-gantt-task_status_done'
          default:
            return ''
        }
      }
    }
  }

5、css部分

5-1、修改dhtmlxGantt 甘特图任务条的颜色

5-2、修改dhtmlxGantt 甘特图背景色

5-3、dhtmlxGantt 甘特图隐藏左侧侧边栏icon展示

<style>
.custom-gantt-level_1_row {
  background-color: #e6f3ff !important; /* 浅蓝色背景 */
}

/*修改任务条主题色*/
.gantt_task_line {
  background-color: #1890FF;
  border: 1px solid #1890FF;
}
.gantt_task_line.custom-gantt-level_1_bar {
  background: #FA8C16 !important;  /* 阶段任务条主色 */
  border-color: #FA8C16 !important;  /* 阶段边框颜色 */
}
.custom-gantt-task_status_done {
  background: #A3B1BF !important;  /* 已完成的任务条主色 */
  border-color: #A3B1BF !important;  /* 已完成的任务边框颜色 */
}

/* 隐藏文件夹图标 */
.gantt_tree_icon.gantt_folder_open,
.gantt_tree_icon.gantt_file,
.gantt_tree_icon.gantt_folder_closed {
  display: none !important;
}

/* 保留展开/收起图标 */
.gantt_grid_icon.gantt_open,
.gantt_tree_icon.gantt_close {
  display: inline-block !important;
  background-position: center; /* 修正图标位置 */
}
/* 调整层级缩进 */
.gantt_tree_indent {
  padding-left: 8px !important; /* 减少缩进间距 */
}
/*修改侧边栏hover颜色*/
.gantt_grid_data .gantt_row.odd:hover,
.gantt_grid_data .gantt_row:hover {
  background-color: #e6f3ff !important;
}
/* 在全局样式表中添加 */
.gantt_tree_text {
  display: inline-block;
  max-width: calc(100% - 24px); /* 为图标留出空间 */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: middle;
}

/*任务条显示不全时样式*/
.gantt_task_content {
  overflow: visible !important; /* 允许溢出显示 */
}
.gantt_task_title {
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none; /* 防止干扰拖拽操作 */
}

</style>

三、使用过程中问题总结

1、页面来回切换,数据更新后甘特图加载数据混乱的问题

使用gantt.clearAll()解决。但要注意再在初始化加载时不需要gantt.clearAll(),所以在再watch监听和初始化可以通过type却分

  watch: {
    '$route.query.id': {
      handler (newId) {
        if (newId) {
          this.loadData('clearAll')
        }
      },
      immediate: true // 立即执行以处理初始加载
    }
  },
  mounted () {
    this.initGantt()
    this.loadData() // 初始化不需要gantt.clearAll()
  },
methods: {
 async loadData (type) {
      ....
      if (type === 'clearAll') { gantt.clearAll() } // 避免来回切换页面更改数据时甘特图数据展示混乱
      // 源代码保持不变
.....
    },
}

2、自定义row背景色,根据状态不同自定义任务条的颜色

gantt.templates.task_class,gantt.templates.task_row_class

// 对应的class见css代码部分
initGantt(){

      // 自定义行样式(关键修改部分)
      gantt.templates.task_row_class = function (start, end, task) {
        if (task.level === 1) {
          return 'custom-gantt-level_1_row'
        }
        return ''
      }
      // 自定义任务条颜色模板(关键代码)
      gantt.templates.task_class = function (start, end, task) {
        // 调试输出(关键)
        // console.log(`[DEBUG] Task ${task.id}:`, {
        //   level: task.level,
        //   status: task.status,
        //   hasLevel: task.hasOwnProperty('level'),
        //   hasStatus: task.hasOwnProperty('status')
        // })
        switch (true) {
          case (task.level === 1):
            return 'custom-gantt-level_1_bar'
          case (task.level === 2 && task.status === 3):
            return 'custom-gantt-task_status_done'
          default:
            return ''
        }
      }

}

3、甘特图文案展示不全问题

甘特图禁止编辑操作后,左侧侧边栏text文案过长时展示不全,可自定义添加title

任务条持续时间短,文案展示不全时,添加title展示

      // 自定义左侧列配置
      gantt.config.columns = [
        { name: 'text',
          label: '任务名称',
          width: '*',
          tree: true,
          // 插入template,title解决字段显示不全的问题
          template: (task) => `
            <div title="${task.text}">
              ${task.text}
            </div>
          `
        },
        { name: 'start_date', label: '开始时间', align: 'center', width: 100 },
        { name: 'duration', label: '持续天数', align: 'center', width: 70 }
      ]

      // 任务条文本模板
      gantt.templates.task_text = (start, end, task) => {
        const cleanText = task.text
          .replace(/</g, '&lt;')
          .replace(/>/g, '&gt;')
          .replace(/"/g, '&quot;')
        return `
          <div class="gantt-task-title" title="${cleanText}">
            ${task.text}
          </div>
        `
      }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2393721.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++高级主题】命令空间(三):未命名的命名空间

目录 一、未命名的命名空间的基本概念 1.1 定义与特点 1.2 基本语法 1.3 访问方式 1.4 未命名的命名空间的作用 二、未命名的命名空间与静态声明的比较 2.1 静态声明的作用 2.2 未命名的命名空间的优势 2.3 示例代码比较 2.4. 未命名的命名空间的作用域和链接属性 三…

VoltAgent 是一个开源 TypeScript 框架,用于构建和编排 AI 代理

​一、软件介绍 文末提供程序和源码下载 VoltAgent 是一个开源 TypeScript 框架&#xff0c;用于构建和编排 AI 代理 二、什么是 VoltAgent&#xff1f; AI 代理框架提供了构建由自主代理提供支持的应用程序所需的基础结构和工具。这些代理通常由大型语言模型 &#xff08;&am…

Unity 中实现首尾无限循环的 ListView

之前已经实现过&#xff1a; Unity 中实现可复用的 ListView-CSDN博客文章浏览阅读5.6k次&#xff0c;点赞2次&#xff0c;收藏27次。源码已放入我的 github&#xff0c;地址&#xff1a;Unity-ListView前言实现一个列表组件&#xff0c;表现方面最核心的部分就是重写布局&…

mongodb集群之副本集

目录 1. 适用场景备份高可用性 2. 集群搭建如何搭建资源规划根据资源完成各节点conf文件的配置启动各个mongodb节点初始化集群信息 搭建实例Linux搭建实例&#xff08;待定&#xff09;Windows搭建实例 3. 副本集基础操作4.集群平滑升级 1. 适用场景 备份 1&#xff09;服务器…

基于微服务架构的社交学习平台WEB系统的设计与实现

设计&#xff08;论文&#xff09;题目 基于微服务架构的社交学习平台WEB系统的设计与实现 摘 要 社交学习平台 web 系统要为学习者打造一个开放、互动且社交性强的在线教育环境&#xff0c;打算采用微服务架构来设计并实现一个社交学习平台 web 系统&#xff0c;以此适应学…

放假带出门的充电宝买哪种好用耐用?倍思超能充35W了解一下!

端午节的到来和毕业季的临近&#xff0c;让很多人开始计划出游或长途旅行。而在旅途中&#xff0c;一款好用耐用的充电宝可以省不少事。今天&#xff0c;我们就来聊聊放假带出门的充电宝买哪种好用耐用&#xff0c;看看为什么倍思超能充35W更适合带出门~ 一、为什么需要一款好用…

AI智能体策略FunctionCalling和ReAct有什么区别?

Dify 内置了两种 Agent 策略&#xff1a;Function Calling 和 ReAct&#xff0c;但二者有什么区别呢&#xff1f;在使用时又该如何选择呢&#xff1f;接下来我们一起来看。 1.Function Calling Function Call 会通过将用户指令映射到预定义函数或工具&#xff0c;LLM 先识别用…

改进自己的图片 app

1. 起因&#xff0c; 目的: 前面我写过一个图片 app &#xff0c; 最新做了些改动。 把原来的一列&#xff0c;改为3列&#xff0c; 继续使用瀑布流手机上使用&#xff0c;更流畅&#xff0c;横屏显示为2列。 2. 先看效果 3. 过程: 过程太细碎了&#xff0c;这里只是做一下…

Uniapp+UView+Uni-star打包小程序极简方案

一、减少主包体积 主包污染源&#xff08;全局文件依赖&#xff09;劲量独立导入 componentsstaticmain.jsApp.vueuni.css 分包配置缺陷&#xff0c;未配置manifest.json中mp-weixin节点 "usingComponents" : true,"lazyCodeLoading" : "requiredC…

算法题(159):快速幂

审题&#xff1a; 本题需要我们计算出(a^b)%c的值&#xff0c;并按照规定格式输出 思路&#xff1a; 方法一&#xff1a;暴力解法 我们直接循环b次计算出a^b,然后再取余c&#xff0c;从而得出最终结果 时间上&#xff1a;会进行2^31次&#xff0c;他的数量级非常大&#xff0c;…

【新品发布】嵌入式人工智能实验箱EDU-AIoT ELF 2正式发布

在万物互联的智能化时代&#xff0c;将AI算法深度植入硬件终端的技术&#xff0c;正悄然改变着工业物联网、智慧交通、智慧医疗等领域的创新边界。为了助力嵌入式人工智能在教育领域实现高质量发展&#xff0c;飞凌嵌入式旗下教育品牌ElfBoard&#xff0c;特别推出嵌入式人工智…

基于javaweb的SpringBoot体检管理系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…

IPD的基础理论与框架——(四)矩阵型组织:打破部门壁垒,构建高效协同的底层

在传统的组织架构中&#xff0c;企业多采用直线职能制&#xff0c;就像一座等级森严的金字塔&#xff0c;信息沿着垂直的层级传递&#xff0c;员工被划分到各个职能部门。这种架构职责清晰、分工明确&#xff0c;在稳定的市场环境中&#xff0c;能让企业高效运作&#xff0c;发…

小程序为什么要安装SSL安全证书

小程序需要部署SSL安全证书&#xff0c;这是小程序开发及运营的强制性要求&#xff0c;也是保障用户数据安全、提升用户体验和满足平台规范的必要措施。 一、平台强制要求 微信小程序官方规范 微信小程序明确要求所有网络请求必须通过HTTPS协议传输&#xff0c;服务器域名需配…

python打卡训练营打卡记录day40

知识点回顾&#xff1a; 彩色和灰度图片测试和训练的规范写法&#xff1a;封装在函数中展平操作&#xff1a;除第一个维度batchsize外全部展平dropout操作&#xff1a;训练阶段随机丢弃神经元&#xff0c;测试阶段eval模式关闭dropout 作业&#xff1a;仔细学习下测试和训练代码…

【清晰教程】利用Git工具将本地项目push上传至GitHub仓库中

Git 是一个分布式版本控制系统&#xff0c;由 Linus Torvalds 创建&#xff0c;用于有效、高速地处理从小到大的项目版本管理。GitHub 是一个基于 Git 的代码托管平台&#xff0c;提供了额外的协作和社交功能&#xff0c;使项目管理更加高效。它们为项目代码管理、团队协作和持…

20250529-C#知识:静态类、静态构造函数和拓展方法

C#知识&#xff1a;静态类、静态构造函数和拓展方法 静态类一般用来编写工具类 1、静态类 用static关键字修饰的类一般充当工具类只能包含静态成员,不能包含静态索引器不能被实例化静态方法只能使用静态成员非静态方法既可以使用非静态成员&#xff0c;也可以使用静态成员 sta…

实验设计与分析(第6版,Montgomery)第4章随机化区组,拉丁方, 及有关设计4.5节思考题4.18~4.19 R语言解题

本文是实验设计与分析&#xff08;第6版&#xff0c;Montgomery著&#xff0c;傅珏生译) 第章随机化区组&#xff0c;拉丁方&#xff0c; 及有关设计4.5节思考题4.18~4.19 R语言解题。主要涉及方差分析&#xff0c;拉丁方。 batch <- c(rep("batch1",5), rep(&quo…

【吾爱】逆向实战crackme160学习记录(一)

前言 最近想拿吾爱上的crackme程序练练手&#xff0c;发现论坛上已经有pk8900总结好的160个crackme&#xff0c;非常方便&#xff0c;而且有很多厉害的前辈已经写好经验贴和方法了&#xff0c;我这里只是做一下自己练习的记录&#xff0c;欢迎讨论学习&#xff0c;感谢吾爱论坛…

vue2 + webpack 老项目升级 node v22 + vite + vue2 实战全记录

前言 随着这些年前端技术的飞速发展&#xff0c;几年前的一些老项目在最新的环境下很可能会出现烂掉的情况。如果项目不需要升级&#xff0c;只需要把编译后的文件放在那里跑而不用管的话还好。但是&#xff0c;某一天产品跑过来给你讲要升级某一个功能&#xff0c;你不得不去…