Vue2中后台使用dhtmlx-gantt插件实现复杂甘特图

2023-10-27

        在工作中由于业务的复杂性,需要使用dhtmlx-gantt来实现复杂表格,以下是甘特图的实现以及一些配置描述。(由于官方文档是英文的,所以对英文不好的不太友好),官方文档:Gantt API Gantt Docs
相关配置:
1、一行需要展示多条数据的操作步骤:需要给父数据的那条添加render:split属性,子数据的parent为父数据的Id即可。
2、配置甘特图的开始和结束时间:

gantt.config.start_date,gantt.config.end_date

3、灯箱中日历设置:

gantt.form_blocks['dhx_calendar'] 

4、表格列设置

gantt.config.columns

5、隐藏某些行的“添加”按钮

gantt.templates.grid_row_class = function (start, end, task) {
    if (task.$level > 1) {
      return 'nested_task'
    }
.nested_task .gantt_add {
  display: none !important;
}
6周末样式突出
gantt.config.work_time = true
    gantt.templates.timeline_cell_class = function (task, date) {
      if (!gantt.isWorkTime(date)) return 'week_end'
    return ''
}
7、节假日样式突出
const holidays = ['2023-03-29']
   const format_date = gantt.date.str_to_date('%Y-%m-%d')
   for (let i = 0; i < holidays.length; i++) {
   const converted_date = format_date(holidays[i])
   gantt.setWorkTime({ date: converted_date, hours: false })
}
注意:dhtmlx.css和dhtmlx.js都要引入index.html

页面代码
<template>
  <div>
    <div ref="ganttYear" id="ganttYearDom" class="gantt-container" style="width: 100%; height: 450px"></div>
  </div>
</template>

<script>
import gantt from 'dhtmlx-gantt'
import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'
import moment from 'moment'
export default {
  name: 'resourcePlan',
  data() {
    return {
      //甘特图
      params: {
        deptIds: [],
        startDate: '',
        endDate: '',
        searchValue: '',
        conditions: [],
      },
      htmlUrl: '',
      // 甘特图数据格式
      dataSource: [],
      ganttHeight: innerHeight - 215 + 'px',
      ganttLoading: false,
      // 下拉框选项
      priorityOptions: [
        { key: '1', label: '编制报告', backgroundColor: '#BD3124', textColor: '#FFF' },
        { key: '2', label: '准备进场新项目', backgroundColor: '#BD3124', textColor: '#FFF' },
        { key: '3', label: '请假休整', backgroundColor: '#81B336', textColor: '#FFF' },
        { key: '4', label: '其他', backgroundColor: '#BD3124', textColor: '#FFF' },
      ],
      tasks: {
        data: [], //甘特图数据
        links: [],
      },
      events: [],
    }
  },
  created() {
    gantt.clearAll()
  },
  mounted() {
    this.init()
  },
  methods: {
    moment,
    // 获取资源统计数据
    getResourceInfo() {
      gantt.config.start_date = this.nowDate.format('YYYY-MM-DD')
      gantt.config.end_date = this.newDate.format('YYYY-MM-DD')
    },
    // 初始化
    init() {
      console.log('初始化')
      //中文
      gantt.i18n.setLocale('cn')
      //自适应甘特图的尺寸大小, 使得在不出现滚动条的情况下, 显示全部任务
      gantt.config.autosize = false
      // 只读模式:打开后不可以操作甘特图
      gantt.config.readonly = false
      gantt.config.date_format = '%Y-%m-%d'
      gantt.config.keep_grid_width = false
      gantt.config.grid_resize = true
      gantt.config.initial_scroll = false

      //是否显示左侧树表格
      gantt.config.show_grid = true
      function byId(list, id) {
        for (var i = 0; i < list.length; i++) {
          if (list[i].key == id) return id || ''
        }
        return ''
      }
      window.byId = byId
      let that = this

      var duration = function (a, b, c) {
        var res = gantt.calculateDuration(a.getDate(false), b.getDate(false))
        c.innerHTML = res + '天'
      }

      var calendar_init = function (id, data, date) {
        var obj = new dhtmlXCalendarObject(id)
        obj.setDateFormat(data.date_format ? data.date_format : '')
        obj.setDate(date ? date : new Date())
        obj.hideTime()
        if (data.skin) obj.setSkin(data.skin)
        return obj
      }
      
      gantt.form_blocks['dhx_calendar'] = {
        render: function (sns) {
          return (
            "<div class='dhx_calendar_cont'><input type='text' readonly='true' id='calendar1'/> &#8211; " +
            "<input type='text' readonly='true' id='calendar2'/><label id='duration'></label></div>"
          )
        },
        set_value: function (node, value, task, data) {
          var a = (node._cal_start = calendar_init('calendar1', data, task.start_date))
          var b = (node._cal_end = calendar_init('calendar2', data, task.end_date))
          var c = node.lastChild

          b.setInsensitiveRange(null, new Date(a.getDate(false) - 86400000))

          var a_click = a.attachEvent('onClick', function (date) {
            b.setInsensitiveRange(null, new Date(date.getTime() - 86400000))
            duration(a, b, c)
          })

          var b_click = b.attachEvent('onClick', function (date) {
            duration(a, b, c)
          })

          var a_time_click = a.attachEvent('onChange', function (d) {
            b.setInsensitiveRange(null, new Date(d.getTime() - 86400000))
            duration(a, b, c)
          })

          var b_time_click = b.attachEvent('onChange', function (d) {
            that.changeEnd = false
            task.end_date = that.setTime(d, true)
            duration(a, b, c)
          })

          var id = gantt.attachEvent('onAfterLightbox', function () {
            a.detachEvent(a_click)
            a.detachEvent(a_time_click)
            a.unload()
            b.detachEvent(b_click)
            b.detachEvent(b_time_click)
            b.unload()
            a = b = null
            this.detachEvent(id)
          })

          document.getElementById('calendar1').value = a.getDate(true)
          document.getElementById('calendar2').value = that.setTime(b.getDate(true), false)
          duration(a, b, c)
        },
        get_value: function (node, task) {
          task.start_date = node._cal_start.getDate(false)
          task.end_date = node._cal_end.getDate(false)
          return task
        },
        focus: function (node) {},
      }
      //表格列设置
      gantt.config.columns = [
        {
          //最左侧新增符号列,甘特图内置可选使用列
          name: 'add',
          label: '',
          width: '40',
        },
        {
          name: 'userName',
          label: '姓名',
          tree: true,
          width: '150',
        },
        {
          name: 'deptName',
          label: '部室',
          width: '100',
        },
        {
          name: 'site',
          label: '现场实施人员',
          hide: true,
        },
        {
          name: 'progorderName',
          label: '程序',
          width: '100',
          hide: true,
        },
        {
          name: 'start_date',
          label: '开始时间',
          hide: true,
        },
        {
          name: 'end_date',
          label: '结束时间',
          hide: true,
        },
        {
          name: 'flag',
          label: '是否调配',
          hide: true,
        },
        {
          name: 'reason',
          label: '不可调配原因',
          template: function (item) {
            return byId(gantt.serverList('staff'), item.reason)
          },
          hide: true,
        },
        {
          name: 'state',
          label: '其他说明',
          hide: true,
        },
      ]
      //自适应
      //gantt.config.fit_tasks = true;

      //连线
      gantt.config.show_links = false

      //表头高度
      gantt.config.scale_height = 80

      //开启提示:鼠标悬浮在gantt行上显示
      gantt.plugins({
        tooltip: true,
      })

      // gantt.config.start_date = new Date(2018,1,1);
      //   gantt.config.end_date = new Date(2020,1,1);

      //周末样式突出
      gantt.config.work_time = true
      gantt.templates.timeline_cell_class = function (task, date) {
        if (!gantt.isWorkTime(date)) return 'week_end'
        return ''
      }

      gantt.templates.task_class = function (start, end, task) {
        var css = []
        if (task.flagStr == 0) {
          css.push('blue_task')
        } else if (task.flagStr == 1) {
          css.push('light_blue_task')
        }

        if (task.reason) {
          css = css.filter((item) => item !== 'blue_task' && item !== 'light_blue_task')
          css.push('gantt_resource_task gantt_resource_' + task.reason)
        }
        return css.join(' ')
      }

      //时间轴格式化模版
      var yearScaleTemplate = function (date) {
        return date.getFullYear()
      }
      var monthScaleTemplate = function (date) {
        var year = date.getFullYear()
        var month = date.getMonth()
        month = month + 1 + '月'
        let yearTemplate = `${year}年${month}`
        return yearTemplate
      }
      //时间轴样式
      var yearScaleCss = function () {
        return 'yearScaleStyle'
      }
      var monthScaleCss = function () {
        return 'monthScaleStyle'
      }

      //定义表头日期
      gantt.config.scales = [
        { unit: 'month', step: 1, format: monthScaleTemplate, css: monthScaleCss },
        { unit: 'day', step: 1, format: '%D <br/> %d' },
        //format: function(date){
        // 	return "<strong>Day " + dayNumber(date) + "</strong><br/>" + dateFormat(date);
        // }
      ]

      //鼠标移动显示信息
      gantt.templates.tooltip_text = function (start, end, task) {
        let endTime = that.setTime(gantt.templates.tooltip_date_format(end), false)
        if (task.render == 'split') {
          return ''
        } else if (task.proGid && task.proGid !== null && task.proGid.indexOf(',') >= 0) {
          let viewTask = ''
          task.taskArr.forEach((item) => {
            viewTask += ``
          })
          return viewTask
        } else if (task.reason == null || task.reason == undefined) {
          return ``
        } else if (task.reason !== null) {
          let obj = that.priorityOptions.find((item) => item.key == task.reason)
          if (obj !== undefined) {
            return '不可调配原因:'
          }
        }
      }

      // 弹框命名文字
      gantt.locale.labels.section_priority = '不可调配原因'
      gantt.locale.labels.section_progorder = '项目名称'
      gantt.locale.labels.section_userName = '姓名'
      gantt.locale.labels.section_deptName = '部室'
      gantt.locale.labels.section_other = '其他说明'
      gantt.locale.labels.message_ok = '确定'
      gantt.locale.labels.confirm_deleting = '是否删除?'

      //配置Gantt内置弹出框元素(title内容)
      gantt.templates.lightbox_header = function (start_date, end_date, task) {
        // return `<b>${task.userName}属性信息</b>`
        return `<b>设置不可调配原因</b>`
      }
      gantt.serverList('staff', that.priorityOptions)
      // 添加弹窗属性
      gantt.config.lightbox.sections = [
        { name: 'priority', height: 30, map_to: 'reason', type: 'select', options: gantt.serverList('staff') },
        { name: 'other', height: 50, map_to: 'state', type: 'textarea', focus: true },
        { name: 'time', type: 'dhx_calendar', map_to: 'auto', skin: '', date_format: '%Y-%m-%d' },
      ]
      // //双击事件
      gantt.config.details_on_dblclick = true
      //关闭所有错误提示信息:gantt有自己的异常消息,如果不关闭可能页面会弹出异常消息
      gantt.config.show_errors = false

      //禁止拖动设置任务长度
      gantt.attachEvent('onBeforeTaskDrag', function (id, mode, e) {
        return false
      })
      //禁止拖动任务
      gantt.config.drag_move = false
      //禁止拖动任务进度
      gantt.config.drag_progress = false
      //禁止拖放添加Link
      gantt.config.drag_links = false

      //任务条显示信息
      gantt.templates.task_text = function (syart, end, task) {
        console.log(task, 'taskkkk')
        // var calendar = gantt.getTaskCalendar(task);
        if (task.reason == 3 || task.reason == 1 || task.reason == 2 || task.reason == 4) {
          let obj = that.priorityOptions.find((item) => item.key == task.reason)
          if (obj !== undefined) {
            return obj.label
          }
        } else {
          if (task.progorderName !== undefined) {
            return task.progorderName
          }
          return ''
        }
      }

      gantt.attachEvent('onParse', function () {
        var styleId = 'dynamicGanttStyles'
        var element = document.getElementById(styleId)
        if (!element) {
          element = document.createElement('style')
          element.id = styleId
          document.querySelector('head').appendChild(element)
        }
        var html = []
        var resources = gantt.serverList('staff')

        resources.forEach(function (r) {
          html.push(
            '.gantt_task_line.gantt_resource_' +
              r.key +
              '{' +
              'background-color:' +
              r.backgroundColor +
              '; ' +
              'color:' +
              r.textColor +
              ';' +
              '}'
          )
          html.push(
            '.gantt_row.gantt_resource_' +
              r.key +
              ' .gantt_cell:nth-child(1) .gantt_tree_content{' +
              'background-color:' +
              r.backgroundColor +
              '; ' +
              'color:' +
              r.textColor +
              ';' +
              '}'
          )
        })
        element.innerHTML = html.join('')
      })

      gantt.attachEvent('onTaskDblClick', function (id, e) {
        if (e.target.className.indexOf('task') == -1) {
          return false
        }
        gantt.showLightbox(id)
        return true
      })

      gantt.config.min_column_width = 40

      //监听按钮保存删除事件  updateResourceReason
      let onBeforeTaskAdd = gantt.attachEvent('onBeforeTaskAdd', function (id, item) {
        let endCopy = JSON.parse(JSON.stringify(item.end_date))
        let endTime = that.setTime(endCopy, false)
        var params = {
          userId: item.parent,
          startDate: moment(item.start_date).format('YYYY-MM-DD'),
          endDate: moment(item.end_date).format('YYYY-MM-DD'),
          // endDate: endTime,
          reason: item.reason,
          state: item.state,
        }
        updateResourceReason(params).then((res) => {
          if (res.code == 0) {
            that.$message.success('新增成功')
            that.getData()
            return true
          } else {
            that.$message.warning(res.msg)
            that.getData()
            return false
          }
        })
      })

      this.events.push(onBeforeTaskAdd)

      let onBeforeTaskUpdate = gantt.attachEvent('onBeforeTaskUpdate', function (id, item) {
        console.log('编辑', id, item)
        // let endCopy = JSON.parse(JSON.stringify(item.end_date))
        // let endTime = that.setTime(endCopy, false)
        let endTime, endCopy
        if (that.changeEnd) {
          endCopy = JSON.parse(JSON.stringify(item.end_date))
          endTime = that.setTime(endCopy, false)
        } else {
          endTime = moment(item.end_date).format('YYYY-MM-DD')
        }
        var params = {
          id: item.reasonId,
          userId: item.userId,
          startDate: moment(item.start_date).format('YYYY-MM-DD'),
          // endDate: moment(item.end_date).format('YYYY-MM-DD'),
          endDate: endTime,
          reason: item.reason,
          state: item.state,
        }
        console.log(7777, item.end_date)
        updateResourceReason(params).then((res) => {
          console.log(1112444, res)
          if (res.code == 0) {
            that.$message.success('更新成功')
            that.getData()
            return true
          } else {
            that.$message.warning(res.msg)
            that.getData()
            return false
          }
        })
      })
      this.events.push(onBeforeTaskUpdate)
      // delResourceReason

      //监听按钮保存删除事件
      let onBeforeTaskDelete = gantt.attachEvent('onBeforeTaskDelete', function (id, item) {
        const params = {
          id: item.reasonId,
          userId: item.userId,
        }
        delResourceReason(params).then((res) => {
          console.log(777, res)
          if (res.code == 0) {
            that.$message.success('删除成功')
            var task = gantt.getTask(id)
            that.getData()
            return true
          } else {
            that.$message.warning(res.msg)
            that.getData()
            return false
          }
        })
      })
      this.events.push(onBeforeTaskDelete)

      gantt.attachEvent('onBeforeLightbox', function (id) {
        that.changeEnd = true
        var task = gantt.getTask(id)
        if (task.flagStr == 0) {
          return false
        }
        return true
      }),
        // 初始化
        setTimeout(() => {
          gantt.clearAll()
          gantt.init(that.$refs.ganttYear)
          gantt.parse(that.tasks)
          document.querySelector('.gantt-container').style.height = '500px'
        }, 1000)
    },
    reload() {
      gantt.clearAll() // 从甘特图中删除所有任务和其他元素(包括标记)
      // gantt.init(this.$refs.ganttYear)
      gantt.parse(this.tasks) // 数据解析
      gantt.render() // 呈现整个甘特图
    },
    getData() {
      var arrTaskNew = []
      this.params.startDate = moment(this.nowDate).format('YYYY-MM-DD')
      this.params.endDate = moment(this.newDate).format('YYYY-MM-DD')
      getCalendarInfo(this.params).then((res) => {
        if (res.code == 0) {
          this.dataSource = res.data
          this.dataSource.forEach((item, index) => {
            item.render = 'split'
            item.id = item.userId
            item.start_date = ''
            item.end_date = ''
            item.type = gantt.config.types.task
            arrTaskNew.push(item)
            if (item.planDtoList !== null) {
              item.planDtoList.forEach((item1, index1) => {
                item1.parent = item.id
                item1.start_date = item1.startDate
                item1.end_date = this.setTime(item1.endDate, true)
                let str = ''
                if (item1.proGid !== null && item1.proGid.indexOf(',') == -1) {
                  item1.personMap[item1.proGid].forEach((item2, index2) => {
                    str += item2.names + '<br/>'
                  })
                  item1.site = str
                  // 如果多个时间相同的任务重叠
                } else if (item1.proGid !== null && item1.proGid.indexOf(',') >= 0) {
                  item1.taskArr = []
                  let proGidArr = item1.proGid.split(',')
                  let progorderNameArr = item1.progorderName.split(',')
                  proGidArr.forEach((item3, index3) => {
                    let objtask = {
                      proGid: '',
                      progorderName: '',
                      names: '',
                    }
                    objtask.proGid = item3
                    objtask.progorderName = progorderNameArr[index3]
                    item1.personMap[item3].forEach((item4, index4) => {
                      objtask.names += item4.names + '<br/>'
                    })
                    item1.taskArr.push(objtask)
                  })
                }
                arrTaskNew.push(item1)
              })
            }
          })

          this.tasks.data = arrTaskNew
          // this.init()
          this.reload()
        } else {
          this.$message.warning(res.msg)
        }
      })
    },
    setTime(date, bool) {
      if (date == null || !date) return null
      var dateTime
      if (typeof date == 'string') {
        dateTime = new Date(date)
      } else {
        dateTime = date
      }
      if (bool) {
        dateTime = dateTime.setDate(dateTime.getDate() + 1)
        dateTime = new Date(dateTime)
      } else {
        dateTime = dateTime.setDate(dateTime.getDate() - 1)
        dateTime = new Date(dateTime)
      }
      if (typeof date == 'string') {
        return this.changeDate(dateTime)
      } else {
        return dateTime
      }
    },
    changeDate(chinaTime) {
      if (typeof date == 'string') return chinaTime
      let m = chinaTime.getMonth() + 1
      let d = chinaTime.getDate()
      if (m >= 0 && m <= 9) {
        m = '0' + m
      }
      if (d >= 0 && d <= 9) {
        d = '0' + d
      }
      return chinaTime.getFullYear() + '-' + m + '-' + d
    },
    queryApi() {},
  },
  computed: {
    ...mapState({
      multiTab: (state) => state.app.multiTab,
    }),
    defaultTime() {
      return [this.nowDate, this.newDate]
    },
  },
  beforeDestroy() {
    this.events.forEach((ele) => {
      gantt.detachEvent(ele)
    })
  },
}
</script>

<style scoped lang="less">
.gantt-container {
  height: 500px;
  min-height: 400px;
  max-height: 800px !important;
  overflow-y: auto !important;
}
.radioRow {
  margin: 10px;
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
}
rsor: pointer;
}
.dhx_calendar_cont input {
  width: 96px;
  padding: 0;
  margin: 3px 10px 10px 10px;
  font-size: 11px;
  height: 17px;
  text-align: center;
  border: 1px solid #ccc;
  color: #646464;
}

.dhtmlxcalendar_dhx_skyblue,
.dhtmlxcalendar_dhx_web,
.dhtmlxcalendar_dhx_terrace {
  z-index: 999999 !important;
}
</style>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Vue2中后台使用dhtmlx-gantt插件实现复杂甘特图 的相关文章

随机推荐

  • QT不允许使用不完整的类型出现原因

    目前遇到的情况如下 1 没有引用头文件 2 没有设置头文件所在路径 或设置路径错误 3 头文件定义出错 此种情况比较常见于新建一个头文件时为了方便直接拷贝已有的头文件来修改 但是图中绿色框框部分没有修改 如下两张图所示 b h由a h复制而
  • 下载pip、安装pip

    下载pip 安装pip 码农家园 Installation pip documentation v23 2 1 如何在 Mac 上安装 PIP https m php cn faq 517564 html pip3 install pyot
  • 一.LLVM基础库初探

    LLVM和Clang被精心组织成如下库 1 libLLVMCore 它包含了与LLVM IR相关的逻辑 IR构造 数据布局 指令 基础块和函数 和IR验证器 它还提供了pass管理器 2 libLLVMAnalysis 将多个IR分析步骤进
  • Maven安装教程详解

    一 准备工作 1 确定电脑上已经成功安装jdk7 0以上版本 2 win10操作系统 3 maven安装包 下载地址 http maven apache org download cgi 二 解压Maven安装包 在上述地址中下载最新的Ma
  • DNS与CDN——前端重点

    DNS的基础知识 1 统一资源定位符 URL 也被称作 网址 用于定位互联网上的资源 2 DNS Domain Name System DNS具体Query过程 3 DNS记录 资源记录 Resource Record DNS的数据库条目
  • 2018-9-11-vue的日期输入 from 表单类型

    注意这个格式
  • mapper时间条件查询

    select
  • Logback configuration error detected: 怎么解决?(亲测有效)

    发生这个错误时首先确认你的xml文件内容是没有问题的 然后检查一下你的properties文件的classpath的配置有没有错 可能的错误如下 错误报没有找到那么就是classpath写错了 或者找到了报IlllegalException
  • C++ 内置类型和类类型的默认初始化和值初始化

    如果定义变量时候没有指定初值 则变量被默认初始化 但是默认初始化还有另外一个含义 在定义内置类型时由于定义变量的位置不同 有可能会不发生初始化操作 这种情况下称为默认初始化 也有可能会给定一个初值 称为值初始化 由上 个人琢磨其实默认初始化
  • 下载文件获取的contentLength 的值是-1的问题

    项目中加了个下载方法 获取的响应中的contentlength值总是 1 查看源码可以看到 用这个int类型的获取的当length大于Int的最大值 2147483647 就返回 1 我需要下载的文件确实大于这个值了 查看源码还有别的获取l
  • 数据库系统-第二章关系数据库 复习

    关系操作 关系数据库基础 关系代数 这个 的写法是错的 因为不存在一个元组的cno既等于c2又等于c4
  • UE4 性能优化方法(工具篇)

    官方文档链接 https docs unrealengine com latest CHN Engine Performance index html 本文依据UE4官方文档以及官方博客等总结而来 可能不全面 后面会陆续添加 内置工具的详细
  • 将Servlet中的ResultSet显示到Jsp页面

    Servlet从数据库中拿到结果以后 对用户来说 他们并不关心你怎么拿的 恰恰最重要的是 他们要看到信息展示在网页上 那这个该怎么实现 言归正传 拿到数据以后 想要把数据展示到Jsp页面上 这样办 跳转 转发和重定看大佬文章 清晰又明白 转
  • vscode连接服务器不用每次都输入密码

    1 首先在自己的本地生成公钥和密钥 git bash 输入以下命令 ssh keygen 然后一路回车 就会在自己用户 ssh文件夹下生成一对密钥 生成的公钥和密钥默认放在 ssh文件夹 我的是 2 修改本地的配置文件 添加下面这行属性到配
  • python学习笔记---IO编程【廖雪峰】

    IO编程 IO在计算机中指Input Output 也就是输入和输出 由于程序和运行时数据是在内存中驻留 由CPU这个超快的计算核心来执行 涉及到数据交换的地方 通常是磁盘 网络等 就需要IO接口 IO编程中 Stream 流 是一个很重要
  • linux中的阻塞机制及等待队列

    阻塞与非阻塞是设备访问的两种方式 驱动程序需要提供阻塞 等待队列 中断 和非阻塞方式 轮询 异步通知 访问设备 在写阻塞与非阻塞的驱动程序时 经常用到等待队列 一 阻塞与非阻塞 阻塞调用是没有获得资源则挂起进程 被挂起的进程进入休眠状态 调
  • 输出数组中最大和最小的元素值及其下标

    设计完整的程序实现以下功能 一个数组有10个元素 例如 1 8 10 2 5 0 7 15 4 5 利用指针作为函数参数 输出数组中最大和最小的元素值及其下标 include
  • TOPP问题(Time-Optimal Path Parameterization)详细解析(附代码)

    题目来源 深蓝学院课程 机器人中的数值优化 主讲 汪哲培博士 最后大作业 参考资料 课程ppt与视频 助教和大佬的提示和讨论 Verscheure D et al Time optimal path tracking for robots
  • java List的contains和remove方法,底层依赖的的对象的equals

    实例 新建一个Person类 像List中添加Person 进行contains和remove方法的测试 Person类 name和age两个属性 但是没有重写equals方法 public class Person private Str
  • Vue2中后台使用dhtmlx-gantt插件实现复杂甘特图

    在工作中由于业务的复杂性 需要使用dhtmlx gantt来实现复杂表格 以下是甘特图的实现以及一些配置描述 由于官方文档是英文的 所以对英文不好的不太友好 官方文档 Gantt API Gantt Docs 相关配置 1 一行需要展示多条