小小儁爺
9 天以前 cb6086934c46f7ac9f277cbdf1203c8f9f9aaf5f
src/views/gantt/index.vue
@@ -1,7 +1,9 @@
<template>
  <div style="padding: 0 10px">
    <!-- 顶部控制栏:包含缩放选择器、优先级选择器、日期范围选择器和操作按钮 -->
    <div style="padding: 10px 0;display: flex;">
      <!-- 时间刻度选择器:用于调整甘特图的时间粒度 -->
      <el-select
        v-model="scaleValue"
        size="mini"
@@ -15,6 +17,7 @@
          :value="item.code"
        />
      </el-select>
      <!-- 优先级方法选择器:设备优先或时间优先 -->
      <el-select
        v-model="priorityMethod"
        size="mini"
@@ -29,6 +32,7 @@
          :value="item.code"
        />
      </el-select>
      <!-- 日期范围选择器:控制甘特图显示的日期范围 -->
      <el-date-picker
        v-model="ganttDateRange"
        style="margin-left: 10px;"
@@ -42,25 +46,30 @@
        end-placeholder="结束日期"
        @change="ganttDateRangeChange"
      />
      <!-- 获取选中任务按钮:获取当前复选框选中的任务 -->
      <el-button type="primary" style="margin-left: 10px;" size="mini" @click="handleGetSelected">
        获取复选框选中任务
      </el-button>
      <!-- 清空选择按钮:清空当前复选框的选择 -->
      <el-button size="mini" @click="handleClearSelection">
        清空复选框选择
      </el-button>
      <!-- 预排按钮:执行预排逻辑 -->
      <el-button size="mini" type="primary" @click="prepareArrange">
        预排
      </el-button>
      <!-- 预排进度显示:显示预排进度统计 -->
      <el-button size="mini" disabled>
        预排进度:{{ canArrangeNumber }}/{{ needArrangeNumber }}
      </el-button>
    </div>
    <!-- 甘特图容器:用于渲染DHTMLX Gantt图表 -->
    <div id="gantt_here" style="width:100%; height:calc(90vh - 50px);" />
    <!-- 分页组件 -->
    <!-- 分页组件:用于分页显示大量任务数据 -->
    <div class="pagination-container">
      <el-pagination
        :current-page="currentPage"
@@ -76,7 +85,7 @@
</template>
<script>
import { gantt } from '@/components/dhtmlxGantt'
import { gantt } from '@/components/dhtmlxGantt' // 目前dhtmlxgantt版本8.0.x
import '@/components/dhtmlxGantt/codebase/dhtmlxgantt.css'
import { handleDateReduceOneDay, handleDatetime, handleDatetime2 } from '@/utils/global'
import { nanoid } from 'nanoid'
@@ -109,9 +118,9 @@
        { code: 'time', name: '时间优先' }
      ],
      pickerOptions: {
        disabledDate(time) {
          return time.getTime() <= Date.now() - 24 * 60 * 60 * 1000
        }
        // disabledDate(time) {
        //   return time.getTime() <= Date.now() - 24 * 60 * 60 * 1000
        // }
      }
    }
  },
@@ -121,9 +130,6 @@
    // 改变日期范围配置
    this.ganttDateRangeChange(this.ganttDateRange)
    // 然后加载任务数据(会自动渲染当前页)
    // this.loadTasks()
  },
  methods: {
@@ -208,7 +214,6 @@
            return `<input type="checkbox" class="taskCheckBox" data-action="check-row" ${checked} />`
          }
        },
        // { name: 'wbs', label: '节点', width: 80, template: gantt.getWBSCode },
        { name: 'text', tree: true, align: 'center', label: '任务名称', width: 240, resize: true, editor: textEditor },
        { name: 'saleOrder', align: 'center', label: '销售订单', width: 100, resize: true },
        { name: 'partName', align: 'center', label: '产品名称', width: 80, resize: true },
@@ -216,7 +221,6 @@
        {
          name: 'progress', align: 'center', label: '进度', width: 120, resize: true, template: function(task) {
            return `<input type="range"  onmousedown="event.preventDefault()" onmouseup="event.preventDefault()" id="taskRange" value="${task.progress * 100}"/> ${task.progress * 100}%`
            // return `<el-progress :percentage='${task.progress * 100}'></el-progress> ${task.progress * 100}%`
          }
        },
        { name: 'start_date', align: 'center', label: '开始日期', width: 80, resize: true, editor: startDateEditor },
@@ -242,8 +246,6 @@
      // 自定义浮动框的显示内容   tooltip浮动框显示的End Date被追加1的问题修复(应该显示数据库的原始值)
      gantt.templates.tooltip_text = function(start, end, task) {
        // return '<b>任务:</b> ' + task.text + '<br/><b>开始时间:</b> ' + `${gantt.date.date_to_str('%Y-%m-%d')(start)}` + '<br/><b>结束时间:</b> ' + handleDateReduceOneDay(end)
        // return '<b>任务:</b> ' + task.text + '<br/><b>开始时间:</b> ' + handleDatetime2(start) + '<br/><b>结束时间:</b> ' + handleDateReduceOneDay(end) + '<br/><b>进度:</b> ' + task.progress * 100 + '%'
        return '<b>任务:</b> ' + task.text +
          '<br/><b>' + `${task.type === 'task' ? '产能' : '生产数量'}` + ' :</b> ' + task.producedCount +
          '<br/><b>进度:</b> ' + task.progress * 100 + '%' +
@@ -252,15 +254,8 @@
      }
      gantt.templates.task_text = function(start, end, task) {
        // return '<span style="color: white; font-weight: bold; text-shadow: 1px 1px 1px #000;">' +
        //   task.description + ' - ' +
        //   '</span>'
        // return task.description
        // return task.progress * 100 + '%'
        if (task.type === 'task2') {
          return `<div  class="task2Css">${task.producedCount}</div>`
          // return task.producedCount
        }
        if (task.type === 'task3') {
          return `<div  class="task3Css">${task.producedCount}</div>`
@@ -268,14 +263,11 @@
        return ''
      }
      // 设置持续时间单位为小时
      // gantt.config.duration_unit = 'hour'
      // 设置持续时间单位为分钟
      gantt.config.duration_unit = 'minute'
      gantt.config.duration_step = 1
      // gantt.config.show_task_cells = false  //隐藏甘特图内部刻度线
      gantt.init('gantt_here')
      // 注意:这里不立即加载数据,而是等待loadTasks被调用
      // 绑定甘特图点击事件(官方推荐的事件委托用法)
      gantt.attachEvent('onTaskClick', (id, e) => {
@@ -305,8 +297,6 @@
      // 初始化完成后同步一次选中状态
      this.syncSelected()
      // this.loadTasks()
    },
    // 加载任务数据
@@ -594,9 +584,24 @@
          item.children.forEach((it, ind) => {
            // 这里应该要生成一个以设备维度为基础的数组   不重不漏
            if (!newArr.map(i => i.partCode).includes(it.AdvaDevicNumber)) {
              console.log(' it.AdvaDevicNumber,', it.AdvaDevicNumber)
              newArr.push({
                id: it.AdvaDevicNumber,
                type: 'project',
                text: '我是父级',
                partName: it.AdvaDevicName,
                partCode: it.AdvaDevicNumber,
                start_date: handleDatetime2(item.YearDate + ' ' + it.OneStartDate.split('~')[0]), // 这个是无效的,只是为了预排prepareArrange方法里面不报错
                end_date: handleDatetime2(item.YearDate + ' ' + it.OneStartDate.split('~')[1]), // 这个是无效的,只是为了预排prepareArrange方法里面不报错
                // duration: this.calculateTimeRangeInMinutes(it.OneStartDate),
                checked: false,
                progress: 0.6,
                parent: 0,
                saleOrder: 'SO-2026-01001',
                open: true
              })
              newArr.push({
                id: it.AdvaDevicNumber + ind.toString(),
                type: 'project',
                text: '任务名称预留',
                partName: it.AdvaDevicName,
@@ -607,7 +612,7 @@
                render: 'split', // 用于在一个工作时间段内显示不下,需要进行分割显示
                checked: false,
                progress: 0,
                parent: 0,
                parent: it.AdvaDevicNumber,
                saleOrder: 'SO-2026-01001'
              })
            }
@@ -617,20 +622,17 @@
              if (it[this.fivePeriodsTimeName[i]]) {
                const duration = this.calculateTimeRangeInMinutes(it[this.fivePeriodsTimeName[i]]) // 工期 单位 分钟
                newArr.push({
                  // id:  index.toString() + ind.toString() + i.toString(),
                  id: nanoid(),
                  type: 'task',
                  text: '任务名称预留',
                  partName: it.AdvaDevicName,
                  partCode: it.AdvaDevicNumber,
                  start_date: handleDatetime2(item.YearDate + ' ' + it[this.fivePeriodsTimeName[i]].split('~')[0]),
                  // start_date: new Date(handleDatetime2(item.YearDate + ' ' + it[this.fivePeriodsTimeName[i]].split('~')[0])).getTime() < new Date().getTime() ? handleDatetime2(new Date()) : handleDatetime2(item.YearDate + ' ' + it[this.fivePeriodsTimeName[i]].split('~')[0]),
                  // end_date: new Date(handleDatetime2(item.YearDate + ' ' + it[this.fivePeriodsTimeName[i]].split('~')[1])).getTime() < new Date().getTime() ? handleDatetime2(new Date()) : handleDatetime2(item.YearDate + ' ' + it[this.fivePeriodsTimeName[i]].split('~')[1]),
                  end_date: handleDatetime2(item.YearDate + ' ' + it[this.fivePeriodsTimeName[i]].split('~')[1]),
                  duration,
                  checked: false,
                  progress: 0,
                  parent: it.AdvaDevicNumber,
                  parent: it.AdvaDevicNumber + ind.toString(),
                  saleOrder: 'SO-2026-01001',
                  //  要在每一个时间段内算出能生产多少个     工期(分钟)乘以60 除以生产节拍 * 稼动率
                  producedCount: (duration * 60 / it.AdvaDevicRhythm) * (it.AdvaDevicCropMob / 100),
@@ -655,11 +657,10 @@
            partCode: item.part_code,
            start_date: item.time_start,
            end_date: item.time_end,
            // duration: this.calculateTimeRangeInMinutes(it.OneStartDate),
            duration: this.calculateTimeRangeInMinutes(item.time_start.split(' ')[1] + '~' + item.time_end.split(' ')[1]),
            checked: false,
            progress: 0,
            parent: item.eqp_code,
            parent: item.eqp_code + '0',
            saleOrder: 'SO-2026-01001',
            producedCount: item.alloc_qty
          })
@@ -694,13 +695,9 @@
      // 使用原有的示例数据作为基础
      this.allTasks = newArr.filter(i => i.schedulingPossible !== false)
      // this.allTasks = newArr
      this.totalTasks = this.allTasks.length
      this.updatePaginatedTasks()
      this.renderGanttChart()
      // this.prepareArrange()
    },
    // 更新分页后的任务数据
@@ -777,7 +774,7 @@
    // 渲染甘特图
    renderGanttChart() {
      gantt.clearAll()
      console.log(JSON.parse(JSON.stringify(this.paginatedTasks)))
      // console.log(JSON.parse(JSON.stringify(this.paginatedTasks)))
      gantt.parse({
        'data': this.paginatedTasks
      })
@@ -787,7 +784,6 @@
    // 页大小改变
    handleSizeChange(newSize) {
      console.log('执行2')
      this.pageSize = newSize
      this.currentPage = 1 // 重置到第一页
      this.updatePaginatedTasks()
@@ -797,7 +793,6 @@
    // 当前页改变
    handleCurrentChange(newPage) {
      console.log('执行1')
      // 计算最大页数,防止超出范围
      const maxPage = Math.ceil(this.totalTasks / this.pageSize)
      if (newPage > maxPage) {
@@ -835,12 +830,11 @@
      // 获取所有选中的任务ID
      // this.selectedIds = [...new Set(this.allTasks.filter(t => t.checked).map(t => t.id))]//数组去重
      this.selectedIds = this.allTasks.filter(t => t.checked).map(t => t.id)
      console.log(this.selectedIds)
    },
    // 获取选中任务(示例)
    handleGetSelected() {
      const selected = this.allTasks.filter(t => t.checked)
      // const selected = this.allTasks.filter(t => t.checked)
      // this.$notify.success(`当前已选中${selected.length} 条任务`)
      this.$notify.success(`点击了`)
    },
@@ -941,14 +935,7 @@
        }
      })
      // for (let i = 0; i < this.allTasks.length; i++) {
      //
      // }
      this.allTasks = [...this.allTasks, ...newArr]
      console.log(JSON.parse(JSON.stringify(this.allTasks)), '888')
      this.totalTasks = this.allTasks.length
      this.updatePaginatedTasks()
      this.renderGanttChart()