UNPKG

vxe-gantt

Version:
2,443 lines • 94.1 kB
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _vue = require("vue");
var _comp = require("../../ui/src/comp");
var _dom = require("../../ui/src/dom");
var _core = require("@vxe-ui/core");
var _util = require("./util");
var _static = require("./static");
var _xeUtils = _interopRequireDefault(require("xe-utils"));
var _ganttHeader = _interopRequireDefault(require("./gantt-header"));
var _ganttBody = _interopRequireDefault(require("./gantt-body"));
var _ganttFooter = _interopRequireDefault(require("./gantt-footer"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const {
  globalEvents
} = _core.VxeUI;
const {
  FinishToStart,
  StartToFinish,
  StartToStart,
  FinishToFinish
} = _static.VxeGanttDependencyType;
const sourceType = 'gantt';
const secondMs = 1000;
const minuteMs = 1000 * 60;
const hourMs = 1000 * 60 * 60;
const dayMs = hourMs * 24;
function getTaskLinkKey(from, to, type) {
  return from + '_' + to + '_' + (type || 0);
}
function createInternalData() {
  return {
    xeTable: null,
    visibleColumn: [],
    startMaps: {},
    endMaps: {},
    chartMaps: {},
    todayDateMaps: {},
    elemStore: {},
    // 存放横向 X 虚拟滚动相关的信息
    scrollXStore: {
      preloadSize: 0,
      offsetSize: 0,
      visibleSize: 0,
      visibleStartIndex: 0,
      visibleEndIndex: 0,
      startIndex: 0,
      endIndex: 0
    },
    // 最后滚动位置
    lastScrollTop: 0,
    lastScrollLeft: 0
  };
}
function createReactData() {
  return {
    // 是否启用了横向 X 可视渲染方式加载
    scrollXLoad: false,
    // 是否启用了纵向 Y 可视渲染方式加载
    scrollYLoad: false,
    // 是否存在纵向滚动条
    overflowY: true,
    // 是否存在横向滚动条
    overflowX: true,
    // 纵向滚动条的宽度
    scrollbarWidth: 0,
    // 横向滚动条的高度
    scrollbarHeight: 0,
    // 最后滚动时间戳
    lastScrollTime: 0,
    lazScrollLoading: false,
    scrollVMLoading: false,
    scrollYHeight: 0,
    scrollYTop: 0,
    isScrollYBig: false,
    scrollXLeft: 0,
    scrollXWidth: 0,
    isScrollXBig: false,
    minViewDate: null,
    maxViewDate: null,
    tableData: [],
    tableColumn: [],
    headerGroups: [],
    viewCellWidth: 40
  };
}
const maxYHeight = 5e6;
// const maxXWidth = 5e6
var _default = exports.default = (0, _comp.defineVxeComponent)({
  name: 'VxeGanttView',
  setup(props, context) {
    const xID = _xeUtils.default.uniqueId();
    const $xeGantt = (0, _vue.inject)('$xeGantt', {});
    const ganttProps = $xeGantt.props;
    const ganttReactData = $xeGantt.reactData;
    const ganttInternalData = $xeGantt.internalData;
    const {
      computeDateFormat,
      computeTaskBarOpts,
      computeTaskViewOpts,
      computeStartField,
      computeEndField,
      computeTypeField,
      computeScrollbarOpts,
      computeScrollbarXToTop,
      computeScrollbarYToLeft,
      computeScaleUnit,
      computeWeekScale,
      computeMinScale,
      computeTaskNowLineOpts,
      computeScaleStep
    } = $xeGantt.getComputeMaps();
    const refElem = (0, _vue.ref)();
    const refScrollXVirtualElem = (0, _vue.ref)();
    const refScrollYVirtualElem = (0, _vue.ref)();
    const refScrollXHandleElem = (0, _vue.ref)();
    const refScrollXLeftCornerElem = (0, _vue.ref)();
    const refScrollXRightCornerElem = (0, _vue.ref)();
    const refScrollYHandleElem = (0, _vue.ref)();
    const refScrollYTopCornerElem = (0, _vue.ref)();
    const refScrollXWrapperElem = (0, _vue.ref)();
    const refScrollYWrapperElem = (0, _vue.ref)();
    const refScrollYBottomCornerElem = (0, _vue.ref)();
    const refScrollXSpaceElem = (0, _vue.ref)();
    const refScrollYSpaceElem = (0, _vue.ref)();
    const refColInfoElem = (0, _vue.ref)();
    const reactData = (0, _vue.reactive)(createReactData());
    const internalData = createInternalData();
    const refMaps = {
      refElem,
      refScrollXHandleElem,
      refScrollYHandleElem
    };
    const computeScaleDateList = (0, _vue.computed)(() => {
      const {
        minViewDate,
        maxViewDate
      } = reactData;
      const taskViewOpts = computeTaskViewOpts.value;
      const minScale = computeMinScale.value;
      const scaleStep = computeScaleStep.value;
      const {
        gridding
      } = taskViewOpts;
      const dateList = [];
      if (!minScale || !minViewDate || !maxViewDate) {
        return dateList;
      }
      const {
        type,
        startDay
      } = minScale;
      let leftSize = -(ganttReactData.currLeftSpacing + _xeUtils.default.toNumber(gridding ? gridding.leftSpacing || 0 : 0));
      let rightSize = ganttReactData.currRightSpacing + _xeUtils.default.toNumber(gridding ? gridding.rightSpacing || 0 : 0);
      if (scaleStep > 0) {
        leftSize *= scaleStep;
        rightSize *= scaleStep;
      }
      switch (type) {
        case 'year':
          {
            let currDate = _xeUtils.default.getWhatYear(minViewDate, leftSize, 'first');
            const endDate = _xeUtils.default.getWhatYear(maxViewDate, rightSize, 'first');
            while (currDate <= endDate) {
              const itemDate = currDate;
              dateList.push(itemDate);
              currDate = _xeUtils.default.getWhatYear(currDate, scaleStep);
            }
            break;
          }
        case 'quarter':
          {
            let currDate = _xeUtils.default.getWhatQuarter(minViewDate, leftSize, 'first');
            const endDate = _xeUtils.default.getWhatQuarter(maxViewDate, rightSize, 'first');
            while (currDate <= endDate) {
              const itemDate = currDate;
              dateList.push(itemDate);
              currDate = _xeUtils.default.getWhatQuarter(currDate, scaleStep);
            }
            break;
          }
        case 'month':
          {
            let currDate = _xeUtils.default.getWhatMonth(minViewDate, leftSize, 'first');
            const endDate = _xeUtils.default.getWhatMonth(maxViewDate, rightSize, 'first');
            while (currDate <= endDate) {
              const itemDate = currDate;
              dateList.push(itemDate);
              currDate = _xeUtils.default.getWhatMonth(currDate, scaleStep);
            }
            break;
          }
        case 'week':
          {
            let currDate = _xeUtils.default.getWhatWeek(minViewDate, leftSize, startDay, startDay);
            const endDate = _xeUtils.default.getWhatWeek(maxViewDate, rightSize, startDay, startDay);
            while (currDate <= endDate) {
              const itemDate = currDate;
              dateList.push(itemDate);
              currDate = _xeUtils.default.getWhatWeek(currDate, scaleStep);
            }
            break;
          }
        case 'day':
        case 'date':
          {
            let currDate = _xeUtils.default.getWhatDay(minViewDate, leftSize, 'first');
            const endDate = _xeUtils.default.getWhatDay(maxViewDate, rightSize, 'first');
            while (currDate <= endDate) {
              const itemDate = currDate;
              dateList.push(itemDate);
              currDate = _xeUtils.default.getWhatDay(currDate, scaleStep);
            }
            break;
          }
        case 'hour':
          {
            let currDate = _xeUtils.default.getWhatHours(minViewDate, leftSize, 'first');
            const endDate = _xeUtils.default.getWhatHours(maxViewDate, rightSize, 'first');
            while (currDate <= endDate) {
              const itemDate = currDate;
              dateList.push(itemDate);
              currDate = _xeUtils.default.getWhatHours(currDate, scaleStep);
            }
            break;
          }
        case 'minute':
          {
            let currDate = _xeUtils.default.getWhatMinutes(minViewDate, leftSize, 'first');
            const endDate = _xeUtils.default.getWhatMinutes(maxViewDate, rightSize, 'first');
            while (currDate <= endDate) {
              const itemDate = currDate;
              dateList.push(itemDate);
              currDate = _xeUtils.default.getWhatMinutes(currDate, scaleStep);
            }
            break;
          }
        case 'second':
          {
            let currDate = _xeUtils.default.getWhatSeconds(minViewDate, leftSize, 'first');
            const endDate = _xeUtils.default.getWhatSeconds(maxViewDate, rightSize, 'first');
            while (currDate <= endDate) {
              const itemDate = currDate;
              dateList.push(itemDate);
              currDate = _xeUtils.default.getWhatSeconds(currDate, scaleStep);
            }
            break;
          }
      }
      return dateList;
    });
    const computeNowLineLeft = (0, _vue.computed)(() => {
      const {
        minViewDate,
        maxViewDate,
        viewCellWidth
      } = reactData;
      const {
        visibleColumn,
        todayDateMaps
      } = internalData;
      const minScale = computeMinScale.value;
      const taskViewOpts = computeTaskViewOpts.value;
      const taskNowLineOpts = computeTaskNowLineOpts.value;
      const {
        showNowLine
      } = taskViewOpts;
      const {
        mode
      } = taskNowLineOpts;
      const {
        nowTime
      } = ganttReactData;
      // 此刻线
      let nlLeft = 0;
      if (showNowLine && minScale && minViewDate && maxViewDate && nowTime >= minViewDate.getTime() && nowTime <= maxViewDate.getTime()) {
        const todayValue = todayDateMaps[minScale.type];
        const todayDate = _xeUtils.default.toStringDate(todayValue);
        let currCol = null;
        let nextCol = null;
        for (let i = 0; i < visibleColumn.length; i++) {
          const column = visibleColumn[i];
          const {
            startDateObj,
            endDateObj
          } = column;
          if (startDateObj.date <= todayDate && endDateObj.date >= todayDate) {
            currCol = column;
            nlLeft = i * viewCellWidth;
            nextCol = visibleColumn[i + 1];
            break;
          }
        }
        if (mode === 'progress') {
          if (currCol && nextCol) {
            const currTime = currCol.dateObj.date.getTime();
            const offsetTime = nowTime - currTime;
            const nowProgress = Math.max(0, Math.min(1, offsetTime / (nextCol.dateObj.date.getTime() - currTime)));
            nlLeft += nowProgress * viewCellWidth;
          }
        } else if (mode === 'center') {
          nlLeft += viewCellWidth / 2;
        } else if (mode === 'end') {
          nlLeft += viewCellWidth - 1;
        }
      }
      return nlLeft;
    });
    const computeMaps = {
      computeScaleDateList,
      computeNowLineLeft
    };
    const $xeGanttView = {
      xID,
      props,
      context,
      reactData,
      internalData,
      getRefMaps: () => refMaps,
      getComputeMaps: () => computeMaps
    };
    const parseStringDate = dateValue => {
      const dateFormat = computeDateFormat.value;
      return _xeUtils.default.toStringDate(dateValue, dateFormat);
    };
    const updateTodayData = () => {
      const {
        taskScaleList
      } = ganttReactData;
      const minScale = computeMinScale.value;
      if (minScale) {
        const weekScale = taskScaleList.find(item => item.type === 'week');
        const isMinWeek = minScale.type === 'week';
        const itemDate = new Date();
        let [yyyy, M, MM, dd, HH, mm, ss] = _xeUtils.default.toDateString(itemDate, 'yyyy-M-MM-dd-HH-mm-ss').split('-');
        const e = itemDate.getDay();
        const E = e + 1;
        const q = Math.ceil((itemDate.getMonth() + 1) / 3);
        const W = `${_xeUtils.default.getYearWeek(itemDate, weekScale ? weekScale.startDay : undefined)}`;
        if (isMinWeek && checkWeekOfsetYear(W, M)) {
          yyyy = `${Number(yyyy) + 1}`;
          M = '1';
          MM = '0' + M;
        }
        ganttReactData.nowTime = itemDate.getTime();
        internalData.todayDateMaps = {
          year: yyyy,
          quarter: `${yyyy}_q${q}`,
          month: `${yyyy}_${MM}`,
          week: `${yyyy}_W${W}`,
          day: `${yyyy}_${MM}_${dd}_E${E}`,
          date: `${yyyy}_${MM}_${dd}`,
          hour: `${yyyy}_${MM}_${dd}_${HH}`,
          minute: `${yyyy}_${MM}_${dd}_${HH}_${mm}`,
          second: `${yyyy}_${MM}_${dd}_${HH}_${mm}_${ss}`
        };
      }
    };
    const handleColumnHeader = () => {
      const {
        taskScaleList
      } = ganttReactData;
      const scaleUnit = computeScaleUnit.value;
      const minScale = computeMinScale.value;
      const weekScale = computeWeekScale.value;
      const scaleDateList = computeScaleDateList.value;
      const scaleStep = computeScaleStep.value;
      const weekStartDay = weekScale ? weekScale.startDay : undefined;
      const fullCols = [];
      const groupCols = [];
      if (minScale && scaleUnit && scaleDateList.length) {
        const renderListMaps = {
          year: [],
          quarter: [],
          month: [],
          week: [],
          day: [],
          date: [],
          hour: [],
          minute: [],
          second: []
        };
        const tempTypeMaps = {
          year: {},
          quarter: {},
          month: {},
          week: {},
          day: {},
          date: {},
          hour: {},
          minute: {},
          second: {}
        };
        const isMinWeek = minScale.type === 'week';
        const handleData = (type, colMaps, minCol) => {
          if (minScale.type === type) {
            return;
          }
          const currCol = colMaps[type];
          const currKey = `${currCol.field}`;
          let currGpCol = tempTypeMaps[type][currKey];
          if (!currGpCol) {
            currGpCol = currCol;
            tempTypeMaps[type][currKey] = currGpCol;
            renderListMaps[type].push(currGpCol);
          }
          if (currGpCol) {
            if (!currGpCol.children) {
              currGpCol.children = [];
            }
            currGpCol.children.push(minCol);
          }
        };
        const createDateObj = date => {
          let [yy, yyyy, M, MM, d, dd, H, HH, m, mm, s, ss] = _xeUtils.default.toDateString(date, 'yy-yyyy-M-MM-d-dd-H-HH-m-mm-s-ss').split('-');
          const e = date.getDay();
          const E = e + 1;
          const q = Math.ceil((date.getMonth() + 1) / 3);
          const W = `${_xeUtils.default.getYearWeek(date, weekScale ? weekScale.startDay : undefined)}`;
          const WW = _xeUtils.default.padStart(W, 2, '0');
          if (isMinWeek && checkWeekOfsetYear(W, M)) {
            yyyy = `${Number(yyyy) + 1}`;
            M = '1';
            MM = '0' + M;
          }
          return {
            date,
            yy,
            yyyy,
            M,
            MM,
            d,
            dd,
            H,
            HH,
            m,
            mm,
            s,
            ss,
            q,
            W,
            WW,
            E,
            e
          };
        };
        for (let i = 0; i < scaleDateList.length; i++) {
          const itemDate = scaleDateList[i];
          const dateObj = createDateObj(itemDate);
          const {
            yyyy,
            MM,
            dd,
            HH,
            mm,
            ss,
            q,
            W,
            E
          } = dateObj;
          const startDateObj = dateObj;
          const colMaps = {
            year: {
              field: yyyy,
              title: yyyy,
              dateObj,
              startDateObj,
              endDateObj: scaleStep > 1 ? createDateObj(_xeUtils.default.getWhatYear(itemDate, scaleStep - 1)) : startDateObj
            },
            quarter: {
              field: `${yyyy}_q${q}`,
              title: `${q}`,
              dateObj,
              startDateObj,
              endDateObj: scaleStep > 1 ? createDateObj(_xeUtils.default.getWhatQuarter(itemDate, scaleStep - 1)) : startDateObj
            },
            month: {
              field: `${yyyy}_${MM}`,
              title: MM,
              dateObj,
              startDateObj,
              endDateObj: scaleStep > 1 ? createDateObj(_xeUtils.default.getWhatMonth(itemDate, scaleStep - 1)) : startDateObj
            },
            week: {
              field: `${yyyy}_W${W}`,
              title: `${W}`,
              dateObj,
              startDateObj,
              endDateObj: scaleStep > 1 ? createDateObj(_xeUtils.default.getWhatWeek(itemDate, scaleStep - 1, weekStartDay, weekStartDay)) : startDateObj
            },
            day: {
              field: `${yyyy}_${MM}_${dd}_E${E}`,
              title: `${E}`,
              dateObj,
              startDateObj,
              endDateObj: scaleStep > 1 ? createDateObj(_xeUtils.default.getWhatDay(itemDate, scaleStep - 1)) : startDateObj
            },
            date: {
              field: `${yyyy}_${MM}_${dd}`,
              title: dd,
              dateObj,
              startDateObj,
              endDateObj: scaleStep > 1 ? createDateObj(_xeUtils.default.getWhatDay(itemDate, scaleStep - 1)) : startDateObj
            },
            hour: {
              field: `${yyyy}_${MM}_${dd}_${HH}`,
              title: HH,
              dateObj,
              startDateObj,
              endDateObj: scaleStep > 1 ? createDateObj(_xeUtils.default.getWhatHours(itemDate, scaleStep - 1)) : startDateObj
            },
            minute: {
              field: `${yyyy}_${MM}_${dd}_${HH}_${mm}`,
              title: mm,
              dateObj,
              startDateObj,
              endDateObj: scaleStep > 1 ? createDateObj(_xeUtils.default.getWhatMinutes(itemDate, scaleStep - 1)) : startDateObj
            },
            second: {
              field: `${yyyy}_${MM}_${dd}_${HH}_${mm}_${ss}`,
              title: ss,
              dateObj,
              startDateObj,
              endDateObj: scaleStep > 1 ? createDateObj(_xeUtils.default.getWhatSeconds(itemDate, scaleStep - 1)) : startDateObj
            }
          };
          const minCol = colMaps[minScale.type];
          if (minScale.level < 19) {
            handleData('year', colMaps, minCol);
          }
          if (minScale.level < 17) {
            handleData('quarter', colMaps, minCol);
          }
          if (minScale.level < 15) {
            handleData('month', colMaps, minCol);
          }
          if (minScale.level < 13) {
            handleData('week', colMaps, minCol);
          }
          if (minScale.level < 11) {
            handleData('day', colMaps, minCol);
          }
          if (minScale.level < 9) {
            handleData('date', colMaps, minCol);
          }
          if (minScale.level < 7) {
            handleData('hour', colMaps, minCol);
          }
          if (minScale.level < 5) {
            handleData('minute', colMaps, minCol);
          }
          if (minScale.level < 3) {
            handleData('second', colMaps, minCol);
          }
          fullCols.push(minCol);
        }
        taskScaleList.forEach(scaleItem => {
          if (scaleItem.type === minScale.type) {
            groupCols.push({
              scaleItem,
              columns: fullCols
            });
            return;
          }
          const list = renderListMaps[scaleItem.type] || [];
          if (list) {
            list.forEach(item => {
              item.childCount = item.children ? item.children.length : 0;
              item.children = undefined;
            });
          }
          groupCols.push({
            scaleItem,
            columns: list
          });
        });
      }
      return {
        fullCols,
        groupCols
      };
    };
    /**
     * 判断周的年份是否跨年
     */
    const checkWeekOfsetYear = (W, M) => {
      return `${W}` === '1' && `${M}` === '12';
    };
    /**
     * 周维度,由于年份和第几周是冲突的行为,所以需要特殊处理,判断是否跨年,例如
     * '2024-12-31' 'yyyy-MM-dd W' >> '2024-12-31 1'
     * '2025-01-01' 'yyyy-MM-dd W' >> '2025-01-01 1'
     */
    const parseWeekObj = (date, firstDay) => {
      const currDate = _xeUtils.default.toStringDate(date);
      let yyyy = currDate.getFullYear();
      const month = currDate.getMonth();
      const weekNum = _xeUtils.default.getYearWeek(currDate, firstDay);
      if (checkWeekOfsetYear(weekNum, month + 1)) {
        yyyy++;
      }
      return {
        yyyy,
        W: weekNum
      };
    };
    const createChartRender = fullCols => {
      const minScale = computeMinScale.value;
      const scaleStep = computeScaleStep.value;
      const scaleUnit = computeScaleUnit.value;
      const weekScale = computeWeekScale.value;
      const dateFormat = computeDateFormat.value;
      if (minScale) {
        const currRatio = scaleStep > 1 ? 1 / scaleStep : 0;
        switch (scaleUnit) {
          case 'year':
            {
              const showActualProgress = /M|d|H|m|s|S/.test(dateFormat);
              const renderFormat = 'yyyy';
              const indexMaps = {};
              fullCols.forEach(({
                dateObj
              }, i) => {
                const currStr = _xeUtils.default.toDateString(dateObj.date, 'yyyy');
                indexMaps[currStr] = i;
                if (currRatio) {
                  let currStep = scaleStep - 1;
                  while (currStep) {
                    const currStr = _xeUtils.default.toDateString(_xeUtils.default.getWhatYear(dateObj.date, scaleStep - currStep), renderFormat);
                    indexMaps[currStr] = i + (scaleStep - currStep) * currRatio;
                    currStep--;
                  }
                }
              });
              return (startValue, endValue) => {
                const startValDate = parseStringDate(startValue);
                const endValDate = parseStringDate(endValue);
                const startStr = _xeUtils.default.toDateString(startValDate, renderFormat);
                const startDate = showActualProgress ? startValDate : _xeUtils.default.getWhatYear(startValDate, 0, 'first');
                const startFirstDate = _xeUtils.default.getWhatYear(startValDate, 0, 'first');
                const endStr = _xeUtils.default.toDateString(endValDate, renderFormat);
                const endDate = showActualProgress ? endValDate : _xeUtils.default.getWhatYear(endValDate, 0, 'last');
                const endFirstDate = _xeUtils.default.getWhatYear(endDate, 0, 'first');
                // 当前是年维度,当指定解析格式精确到天时,显示实际进度
                let startSubtractSize = 0;
                let endSubtractSize = 1;
                if (showActualProgress) {
                  // 按年的天数比计算
                  const syDaySize = _xeUtils.default.getDayOfYear(startDate, 0);
                  startSubtractSize = (startDate.getTime() - startFirstDate.getTime()) / dayMs / syDaySize;
                  const eyDaySize = _xeUtils.default.getDayOfYear(endDate, 0);
                  endSubtractSize = (endDate.getTime() - endFirstDate.getTime()) / dayMs / eyDaySize;
                  if (currRatio) {
                    startSubtractSize *= currRatio;
                    endSubtractSize *= currRatio;
                  }
                }
                const offsetLeftSize = (indexMaps[startStr] || 0) + startSubtractSize;
                return {
                  offsetLeftSize,
                  offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + endSubtractSize
                };
              };
            }
          case 'quarter':
            {
              const showActualProgress = /M|d|H|m|ss|S/.test(dateFormat);
              const renderFormat = 'yyyy-q';
              const indexMaps = {};
              fullCols.forEach(({
                dateObj
              }, i) => {
                const currStr = _xeUtils.default.toDateString(dateObj.date, renderFormat);
                indexMaps[currStr] = i;
                if (currRatio) {
                  let currStep = scaleStep - 1;
                  while (currStep) {
                    const currStr = _xeUtils.default.toDateString(_xeUtils.default.getWhatQuarter(dateObj.date, scaleStep - currStep), renderFormat);
                    indexMaps[currStr] = i + (scaleStep - currStep) * currRatio;
                    currStep--;
                  }
                }
              });
              return (startValue, endValue) => {
                const startValDate = parseStringDate(startValue);
                const endValDate = parseStringDate(endValue);
                const startStr = _xeUtils.default.toDateString(startValDate, renderFormat);
                const startDate = showActualProgress ? startValDate : _xeUtils.default.getWhatQuarter(startValDate, 0, 'first');
                const startFirstDate = _xeUtils.default.getWhatQuarter(startValDate, 0, 'first');
                const endStr = _xeUtils.default.toDateString(endValDate, renderFormat);
                const endDate = showActualProgress ? endValDate : _xeUtils.default.getWhatQuarter(endValDate, 0, 'last');
                const endFirstDate = _xeUtils.default.getWhatQuarter(endDate, 0, 'first');
                // 当前是季度维度,当指定解析格式精确到天时,显示实际进度
                let startSubtractSize = 0;
                let endSubtractSize = 1;
                if (showActualProgress) {
                  // 按季度天数比计算
                  const sqDaySize = _xeUtils.default.getDayOfQuarter(startDate, 0);
                  startSubtractSize = (startDate.getTime() - startFirstDate.getTime()) / dayMs / sqDaySize;
                  const eqDaySize = _xeUtils.default.getDayOfQuarter(endDate, 0);
                  endSubtractSize = (endDate.getTime() - endFirstDate.getTime()) / dayMs / eqDaySize;
                  if (currRatio) {
                    startSubtractSize *= currRatio;
                    endSubtractSize *= currRatio;
                  }
                }
                const offsetLeftSize = (indexMaps[startStr] || 0) + startSubtractSize;
                return {
                  offsetLeftSize,
                  offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + endSubtractSize
                };
              };
            }
          case 'month':
            {
              const renderFormat = 'yyyy-MM';
              const showActualProgress = /d|H|m|ss|S/.test(dateFormat);
              const indexMaps = {};
              fullCols.forEach(({
                dateObj
              }, i) => {
                const currStr = _xeUtils.default.toDateString(dateObj.date, renderFormat);
                indexMaps[currStr] = i;
                if (currRatio) {
                  let currStep = scaleStep - 1;
                  while (currStep) {
                    const currStr = _xeUtils.default.toDateString(_xeUtils.default.getWhatMonth(dateObj.date, scaleStep - currStep), renderFormat);
                    indexMaps[currStr] = i + (scaleStep - currStep) * currRatio;
                    currStep--;
                  }
                }
              });
              return (startValue, endValue) => {
                const startValDate = parseStringDate(startValue);
                const endValDate = parseStringDate(endValue);
                const startStr = _xeUtils.default.toDateString(startValDate, renderFormat);
                const startDate = showActualProgress ? startValDate : _xeUtils.default.getWhatMonth(startValDate, 0, 'first');
                const startFirstDate = _xeUtils.default.getWhatMonth(startValDate, 0, 'first');
                const endStr = _xeUtils.default.toDateString(endValDate, renderFormat);
                const endDate = showActualProgress ? endValDate : _xeUtils.default.getWhatMonth(endValDate, 0, 'last');
                const endFirstDate = _xeUtils.default.getWhatMonth(endDate, 0, 'first');
                // 当前是月维度,当指定解析格式精确到天时,显示实际进度
                let startSubtractSize = 0;
                let endSubtractSize = 1;
                if (showActualProgress) {
                  // 按月天数比计算
                  const smDaySize = _xeUtils.default.getDayOfMonth(startDate, 0);
                  startSubtractSize = (startDate.getTime() - startFirstDate.getTime()) / dayMs / smDaySize;
                  const emDaySize = _xeUtils.default.getDayOfMonth(endDate, 0);
                  endSubtractSize = (endDate.getTime() - endFirstDate.getTime()) / dayMs / emDaySize;
                  if (currRatio) {
                    startSubtractSize *= currRatio;
                    endSubtractSize *= currRatio;
                  }
                }
                const offsetLeftSize = (indexMaps[startStr] || 0) + startSubtractSize;
                return {
                  offsetLeftSize,
                  offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + endSubtractSize
                };
              };
            }
          case 'week':
            {
              const weekStartDay = weekScale ? weekScale.startDay : undefined;
              const showActualProgress = /d|H|m|s|S/.test(dateFormat);
              const indexMaps = {};
              fullCols.forEach(({
                dateObj
              }, i) => {
                const currStr = `${dateObj.yyyy}-${dateObj.W}`;
                indexMaps[currStr] = i;
                if (currRatio) {
                  let currStep = scaleStep - 1;
                  while (currStep) {
                    const offsetDate = _xeUtils.default.getWhatWeek(dateObj.date, scaleStep - currStep, weekStartDay, weekStartDay);
                    let [yyyy, M] = _xeUtils.default.toDateString(offsetDate, 'yyyy-M-MM-dd-HH-mm-ss').split('-');
                    const W = `${_xeUtils.default.getYearWeek(offsetDate, weekScale ? weekScale.startDay : undefined)}`;
                    if (checkWeekOfsetYear(W, M)) {
                      yyyy = `${Number(yyyy) + 1}`;
                    }
                    const currStr = `${yyyy}-${W}`;
                    indexMaps[currStr] = i + (scaleStep - currStep) * currRatio;
                    currStep--;
                  }
                }
              });
              return (startValue, endValue) => {
                const startValDate = parseStringDate(startValue);
                const endValDate = parseStringDate(endValue);
                const startDate = showActualProgress ? startValDate : _xeUtils.default.getWhatWeek(startValDate, 0, 'first', weekStartDay);
                const startWeekObj = parseWeekObj(startDate, weekStartDay);
                const startStr = `${startWeekObj.yyyy}-${startWeekObj.W}`;
                const startFirstDate = _xeUtils.default.getWhatWeek(startDate, 0, 'first', weekStartDay);
                const endDate = showActualProgress ? endValDate : _xeUtils.default.getWhatWeek(endValDate, 0, 'first', weekStartDay);
                const endWeekObj = parseWeekObj(endDate, weekStartDay);
                const endStr = `${endWeekObj.yyyy}-${endWeekObj.W}`;
                const endFirstDate = _xeUtils.default.getWhatWeek(endDate, 0, 'first', weekStartDay);
                // 当前是周维度,当指定解析格式精确到天时,显示实际进度
                let startSubtractSize = 0;
                let endSubtractSize = 1;
                if (showActualProgress) {
                  // 按周天数比计算
                  startSubtractSize = (startDate.getTime() - startFirstDate.getTime()) / dayMs / 7;
                  endSubtractSize = (endDate.getTime() - endFirstDate.getTime()) / dayMs / 7;
                  if (currRatio) {
                    startSubtractSize *= currRatio;
                    endSubtractSize *= currRatio;
                  }
                }
                const offsetLeftSize = (indexMaps[startStr] || 0) + startSubtractSize;
                return {
                  offsetLeftSize,
                  offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + endSubtractSize
                };
              };
            }
          case 'day':
          case 'date':
            {
              const renderFormat = 'yyyy-MM-dd';
              const showActualProgress = /H|m|s|S/.test(dateFormat);
              const indexMaps = {};
              fullCols.forEach(({
                dateObj
              }, i) => {
                const currStr = _xeUtils.default.toDateString(dateObj.date, renderFormat);
                indexMaps[currStr] = i;
                if (currRatio) {
                  let currStep = scaleStep - 1;
                  while (currStep) {
                    const currStr = _xeUtils.default.toDateString(_xeUtils.default.getWhatDay(dateObj.date, scaleStep - currStep), renderFormat);
                    indexMaps[currStr] = i + (scaleStep - currStep) * currRatio;
                    currStep--;
                  }
                }
              });
              return (startValue, endValue) => {
                const startValDate = parseStringDate(startValue);
                const endValDate = parseStringDate(endValue);
                const startStr = _xeUtils.default.toDateString(startValDate, renderFormat);
                const startDate = showActualProgress ? startValDate : _xeUtils.default.getWhatDay(startValDate, 0, 'first');
                const startFirstDate = _xeUtils.default.getWhatDay(startDate, 0, 'first');
                const endStr = _xeUtils.default.toDateString(endValDate, renderFormat);
                const endDate = showActualProgress ? endValDate : _xeUtils.default.getWhatDay(endValDate, 0, 'last');
                const endFirstDate = _xeUtils.default.getWhatDay(endDate, 0, 'first');
                // 当前是天维度,当指定解析格式精确到时分秒豪秒时,显示实际进度
                let startSubtractSize = 0;
                let endSubtractSize = 1;
                if (showActualProgress) {
                  startSubtractSize = (startDate.getTime() - startFirstDate.getTime()) / dayMs;
                  endSubtractSize = (endDate.getTime() - endFirstDate.getTime()) / dayMs;
                  if (currRatio) {
                    startSubtractSize *= currRatio;
                    endSubtractSize *= currRatio;
                  }
                }
                const offsetLeftSize = (indexMaps[startStr] || 0) + startSubtractSize;
                return {
                  offsetLeftSize,
                  offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + endSubtractSize
                };
              };
            }
          case 'hour':
            {
              const renderFormat = 'yyyy-MM-dd HH';
              const showActualProgress = /m|s|S/.test(dateFormat);
              const indexMaps = {};
              fullCols.forEach(({
                dateObj
              }, i) => {
                const currStr = _xeUtils.default.toDateString(dateObj.date, renderFormat);
                indexMaps[currStr] = i;
                if (currRatio) {
                  let currStep = scaleStep - 1;
                  while (currStep) {
                    const currStr = _xeUtils.default.toDateString(_xeUtils.default.getWhatHours(dateObj.date, scaleStep - currStep), renderFormat);
                    indexMaps[currStr] = i + (scaleStep - currStep) * currRatio;
                    currStep--;
                  }
                }
              });
              return (startValue, endValue) => {
                const startValDate = parseStringDate(startValue);
                const endValDate = parseStringDate(endValue);
                const startStr = _xeUtils.default.toDateString(startValDate, renderFormat);
                const startDate = showActualProgress ? startValDate : _xeUtils.default.getWhatHours(startValDate, 0, 'first');
                const startFirstDate = _xeUtils.default.getWhatHours(startDate, 0, 'first');
                const endStr = _xeUtils.default.toDateString(endValDate, renderFormat);
                const endDate = showActualProgress ? endValDate : _xeUtils.default.getWhatHours(endValDate, 0, 'last');
                const endFirstDate = _xeUtils.default.getWhatHours(endDate, 0, 'first');
                // 当前是小时维度,当指定解析格式精确到分秒豪秒时,显示实际进度
                let startSubtractSize = 0;
                let endSubtractSize = 1;
                if (showActualProgress) {
                  startSubtractSize = (startDate.getTime() - startFirstDate.getTime()) / hourMs;
                  endSubtractSize = (endDate.getTime() - endFirstDate.getTime()) / hourMs;
                  if (currRatio) {
                    startSubtractSize *= currRatio;
                    endSubtractSize *= currRatio;
                  }
                }
                const offsetLeftSize = (indexMaps[startStr] || 0) + startSubtractSize;
                return {
                  offsetLeftSize,
                  offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + endSubtractSize
                };
              };
            }
          case 'minute':
            {
              const renderFormat = 'yyyy-MM-dd HH:mm';
              const showActualProgress = /s|S/.test(dateFormat);
              const indexMaps = {};
              fullCols.forEach(({
                dateObj
              }, i) => {
                const currStr = _xeUtils.default.toDateString(dateObj.date, renderFormat);
                indexMaps[currStr] = i;
                if (currRatio) {
                  let currStep = scaleStep - 1;
                  while (currStep) {
                    const currStr = _xeUtils.default.toDateString(_xeUtils.default.getWhatMinutes(dateObj.date, scaleStep - currStep), renderFormat);
                    indexMaps[currStr] = i + (scaleStep - currStep) * currRatio;
                    currStep--;
                  }
                }
              });
              return (startValue, endValue) => {
                const startValDate = parseStringDate(startValue);
                const endValDate = parseStringDate(endValue);
                const startStr = _xeUtils.default.toDateString(startValDate, renderFormat);
                const startDate = showActualProgress ? startValDate : _xeUtils.default.getWhatMinutes(startValDate, 0, 'first');
                const startFirstDate = _xeUtils.default.getWhatMinutes(startDate, 0, 'first');
                const endStr = _xeUtils.default.toDateString(endValDate, renderFormat);
                const endDate = showActualProgress ? endValDate : _xeUtils.default.getWhatMinutes(endValDate, 0, 'last');
                const endFirstDate = _xeUtils.default.getWhatMinutes(endDate, 0, 'first');
                // 当前是分钟维度,当指定解析格式精确到秒豪秒时,显示实际进度
                let startSubtractSize = 0;
                let endSubtractSize = 1;
                if (showActualProgress) {
                  startSubtractSize = (startDate.getTime() - startFirstDate.getTime()) / minuteMs;
                  endSubtractSize = (endDate.getTime() - endFirstDate.getTime()) / minuteMs;
                  if (currRatio) {
                    startSubtractSize *= currRatio;
                    endSubtractSize *= currRatio;
                  }
                }
                const offsetLeftSize = (indexMaps[startStr] || 0) + startSubtractSize;
                return {
                  offsetLeftSize,
                  offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + endSubtractSize
                };
              };
            }
          case 'second':
            {
              const renderFormat = 'yyyy-MM-dd HH:mm:ss';
              const showActualProgress = /S/.test(dateFormat);
              const indexMaps = {};
              fullCols.forEach(({
                dateObj
              }, i) => {
                const currStr = _xeUtils.default.toDateString(dateObj.date, renderFormat);
                indexMaps[currStr] = i;
                if (currRatio) {
                  let currStep = scaleStep - 1;
                  while (currStep) {
                    const currStr = _xeUtils.default.toDateString(_xeUtils.default.getWhatSeconds(dateObj.date, scaleStep - currStep), renderFormat);
                    indexMaps[currStr] = i + (scaleStep - currStep) * currRatio;
                    currStep--;
                  }
                }
              });
              return (startValue, endValue) => {
                const startValDate = parseStringDate(startValue);
                const endValDate = parseStringDate(endValue);
                const startStr = _xeUtils.default.toDateString(startValDate, renderFormat);
                const startDate = showActualProgress ? startValDate : _xeUtils.default.getWhatSeconds(startValDate, 0, 'first');
                const startFirstDate = _xeUtils.default.getWhatSeconds(startDate, 0, 'first');
                const endStr = _xeUtils.default.toDateString(endValDate, renderFormat);
                const endDate = showActualProgress ? endValDate : _xeUtils.default.getWhatSeconds(endValDate, 0, 'last');
                const endFirstDate = _xeUtils.default.getWhatSeconds(endDate, 0, 'first');
                // 当前是秒维度,当指定解析格式精确到豪秒时,显示实际进度
                let startSubtractSize = 0;
                let endSubtractSize = 1;
                if (showActualProgress) {
                  startSubtractSize = (startDate.getTime() - startFirstDate.getTime()) / secondMs;
                  endSubtractSize = (endDate.getTime() - endFirstDate.getTime()) / secondMs;
                  if (currRatio) {
                    startSubtractSize *= currRatio;
                    endSubtractSize *= currRatio;
                  }
                }
                const offsetLeftSize = (indexMaps[startStr] || 0) + startSubtractSize;
                return {
                  offsetLeftSize,
                  offsetWidthSize: (indexMaps[endStr] || 0) - offsetLeftSize + endSubtractSize
                };
              };
            }
        }
      }
      return () => {
        return {
          offsetLeftSize: 0,
          offsetWidthSize: 0
        };
      };
    };
    const handleParseColumn = () => {
      const ganttProps = $xeGantt.props;
      const {
        treeConfig
      } = ganttProps;
      const {
        minViewDate,
        maxViewDate
      } = reactData;
      const {
        fullCols,
        groupCols
      } = handleColumnHeader();
      if (minViewDate && maxViewDate && fullCols.length) {
        const $xeTable = internalData.xeTable;
        if ($xeTable) {
          const startField = computeStartField.value;
          const endField = computeEndField.value;
          const typeField = computeTypeField.value;
          const {
            computeAggregateOpts,
            computeTreeOpts
          } = $xeTable.getComputeMaps();
          const tableReactData = $xeTable.reactData;
          const {
            isRowGroupStatus
          } = tableReactData;
          const tableInternalData = $xeTable.internalData;
          const {
            afterFullData,
            afterTreeFullData,
            afterGroupFullData
          } = tableInternalData;
          const aggregateOpts = computeAggregateOpts.value;
          const treeOpts = computeTreeOpts.value;
          const {
            transform
          } = treeOpts;
          const childrenField = treeOpts.children || treeOpts.childrenField;
          const ctMaps = {};
          const renderFn = createChartRender(fullCols);
          const handleParseRender = row => {
            const rowid = $xeTable.getRowid(row);
            let startValue = _xeUtils.default.get(row, startField);
            let endValue = _xeUtils.default.get(row, endField);
            const renderTaskType = (0, _util.getTaskType)(_xeUtils.default.get(row, typeField));
            const isMilestone = (0, _util.hasMilestoneTask)(renderTaskType);
            const isSubview = (0, _util.hasSubviewTask)(renderTaskType);
            if (isMilestone) {
              if (!startValue) {
                startValue = endValue;
              }
              endValue = startValue;
            }
            if (isSubview) {
              ctMaps[rowid] = {
                row,
                rowid,
                oLeftSize: 0,
                oWidthSize: 0
              };
            } else if (startValue && endValue) {
              const {
                offsetLeftSize,
                offsetWidthSize
              } = renderFn(startValue, endValue);
              ctMaps[rowid] = {
                row,
                rowid,
                oLeftSize: offsetLeftSize,
                oWidthSize: offsetWidthSize
              };
            }
          };
          if (isRowGroupStatus) {
            // 行分组
            const mapChildrenField = aggregateOpts.mapChildrenField;
            if (mapChildrenField) {
              _xeUtils.default.eachTree(afterGroupFullData, handleParseRender, {
                children: mapChildrenField
              });
            }
          } else if (treeConfig) {
            // 树结构
            _xeUtils.default.eachTree(afterTreeFullData, handleParseRender, {
              children: transform ? treeOpts.mapChildrenField : childrenField
            });
          } else {
            afterFullData.forEach(handleParseRender);
          }
          internalData.chartMaps = ctMaps;
        }
      }
      internalData.visibleColumn = fullCols;
      reactData.headerGroups = groupCols;
      updateTodayData();
      updateScrollXStatus();
      handleTableColumn();
    };
    const handleUpdateData = () => {
      const {
        linkList
      } = ganttReactData;
      const {
        treeConfig
      } = ganttProps;
      const {
        scrollXStore
      } = internalData;
      const $xeTable = internalData.xeTable;
      const sdMaps = {};
      const edMaps = {};
      let minDate = null;
      let maxDate = null;
      const allList = [];
      if ($xeTable) {
        const startField = computeStartField.value;
        const endField = computeEndField.value;
        const typeField = computeTypeField.value;
        const {
          computeAggregateOpts,
          computeTreeOpts
        } = $xeTable.getComputeMaps();
        const tableReactData = $xeTable.reactData;
        const {
          isRowGroupStatus
        } = tableReactData;
        const tableInternalData = $xeTable.internalData;
        const {
          afterFullData,
          afterTreeFullData,
          afterGroupFullData
        } = tableInternalData;
        const aggregateOpts = computeAggregateOpts.value;
        const treeOpts = computeTreeOpts.value;
        const {
          transform
        } = treeOpts;
        const childrenField = treeOpts.children || treeOpts.childrenField;
        const handleMinMaxData = row => {
          let startValue = _xeUtils.default.get(row, startField);
          let endValue = _xeUtils.default.get(row, endField);
          const typeValue = _xeUtils.default.get(row, typeField);
          const isMilestone = (0, _util.hasMilestoneTask)(typeValue);
          if (!startValue) {
            startValue = endValue;
          }
          if (isMilestone || !endValue) {
            endValue = startValue;
          }
          if (startValue) {
            const startDate = parseStringDate(startValue);
            if (!minDate || minDate.getTime() > startDate.getTime()) {
              minDate = startDate;
            }
          }
          if (endValue) {
            const endDate = parseStringDate(endValue);
            if (!maxDate || maxDate.getTime() < endDate.getTime()) {
              maxDate = endDate;
            }
          }
          allList.push(row);
        };
        if (isRowGroupStatus) {
          // 行分组
          const mapChildrenField = aggregateOpts.mapChildrenField;
          if (mapChildrenField) {
            _xeUtils.default.eachTree(afterGroupFullData, handleMinMaxData, {
              children: mapChildrenField
            });
          }
        } else if (treeConfig) {
          // 树结构
          _xeUtils.default.eachTree(afterTreeFullData, handleMinMaxData, {
            children: transform ? treeOpts.mapChildrenField : childrenField
          });
        } else {
          afterFullData.forEach(handleMinMaxData);
        }
      }
      scrollXStore.startIndex = 0;
      scrollXStore.endIndex = Math.max(1, scrollXStore.visibleSize);
      reactData.minViewDate = minDate;
      reactData.maxViewDate = maxDate;
      internalData.startMaps = sdMaps;
      internalData.endMaps = edMaps;
      handleParseColumn();
      handleCriticalPath(allList, linkList);
    };
    /**
     * 正向:后置 ES 的下连接线
     */
    function forwardCriticalPathLowerBound(linkType, predES, predEF, duration) {
      switch (linkType) {
        case FinishToStart:
          return predEF;
        case StartToFinish:
          return predES - duration;
        case StartToStart:
          return predES;
        case FinishToFinish:
          return predEF - duration;
        default:
          return 0;
      }
    }
    /**
     * 反向:前置 LF 的上连接线
     */
    function backwardCriticalPathUpperBound(linkType, succLS, succLF, duration) {
      switch (linkType) {
        case FinishToStart:
          return succLS;
        case StartToFinish:
          return succLF + duration;
        case StartToStart:
          return succLS + duration;
        case FinishToFinish:
          return succLF;
        default:
          return -1;
      }
    }
    /**
     * 关键边:两端都关键时,约束是否连接
     */
    function isCriticalPathLinkTight(linkType, fromES, fromEF, toES, toEF, tolerance) {
      switch (linkType) {
        case FinishToStart:
          return Math.abs(fromEF - toES) < tolerance;
        case StartToFinish:
          return Math.abs(fromES - toEF) < tolerance;
        case StartToStart:
          return Math.abs(fromES - toES) < tolerance;
        case FinishToFinish:
          return Math.abs(fromEF - toEF) < tolerance;
        default:
          return false;
      }
    }
    function handleCriticalPath(data, links) {
      const taskBarOpts = computeTaskBarOpts.value;
      const $xeTable = internalData.xeTable;
      const criticalRowList = [];
      const criticalRowMaps = new Map();
      const criticalLinkKeyMaps = new Map();
      ganttInternalData.criticalRowList = criticalRowList;
      ganttInternalData.criticalRowMaps = criticalRowMaps;
      ganttInternalData.criticalLinkKeyMaps = criticalLinkKeyMaps;
      if (!taskBarOpts.showCriticalPath || !links.length || !data.length || !$xeTable) {
        if (ganttReactData.criticalRowIds.length || ganttReactData.criticalLinks.length) {
          ganttReactData.criticalPathFlag++;
        }
        ganttReactData.criticalLinks = [];
        ganttReactData.criticalRowIds = [];
        return;
      }
      const {
        chartMaps
      } = internalData;
      const tolerance = 1e-6;
      const nodeMap = new Map();
      for (const row of data) {
        const rowid = $xeTable.getRowid(row);
        const chartRest = chartMaps[rowid];
        nodeMap.set(rowid, {
          row,
          rowid: rowid,
          duration: chartRest ? chartRest.oWidthSize : 0,
          incoming: [],
          outgoing: [],
          indeg: 0,
          ES: 0,
          EF: 0,
          LS: 0,
          LF: 0
        });
      }
      // 边界
      const linkList = [];
      for (const link of links) {
        const fromKey = '' + link.from;
        const toKey = '' + link.to;
        if (!nodeMap.has(fromKey) || !nodeMap.has(toKey) || fromKey === toKey) {
          continue;
        }
        const lkItemitem = {
          from: link.from,
          to: link.to,
          type: _xeUtils.default.toNumber(link.type) || 0,
          raw: link
        };
        linkList.push(lkItemitem);
        const toObjItem = nodeMap.get('' + link.to);
        const fromObjItem = nodeMap.get('' + link.from);
        if (fromObjItem) {
          fromObjItem.outgoing.push(lkItemitem);
        }
        if (toObjItem) {
          toObjItem.incoming.push(lkItemitem);
          toObjItem.indeg++;
        }
      }
      // 拓扑排序 + 环检测
      const queueList = [];
      nodeMap.forEach(nodeitem => {
        if (nodeitem.indeg === 0) {
          queueList.push(nodeitem);
        }
      });
      const orderList = [];
      for (let head = 0; head < queueList.length; head++) {
        const node = queueList[head];
        orderList.push(node);
        for (const lkItemitem of node.outgoing) {
          const toObjItem = nodeMap.get('' + lkItemitem.to);
          if (toObjItem) {
            const nextDeg = toObjItem.indeg - 1;
            toObjItem.indeg = nextDeg;
            if (nextDeg === 0) {
              queueList.push(nodeMap.get('' + lkItemitem.to));
            }
          }
        }
      }
      if (orderList.length !== nodeMap.size) {
        // 异常数据,依赖图中存在环
        if (ganttReactData.criticalRowIds.length || ganttReactData.criticalLinks.length) {
          ganttReactData.criticalPathFlag++;
        }
        ganttReactData.criticalLinks = [];
        ganttReactData.criticalRowIds = [];
        return;
      }
      // 正向:ES / EF
      let criticalDuration = 0;
      for (const node of orderList) {
        let earliestStart = 0;
        for (const lkItem of node.incoming) {
          const fromObjItem = nodeMap.get('' + lkItem.from);
          if (fromObjItem) {
            const need = forwardCriticalPathLowerBound(lkItem.type, fromObjItem.ES, fromObjItem.EF, node.duration);
            if (need > earliestStart) {
              earliestStart = need;
            }
          }
        }
        node.ES = earliestStart;
        node.EF = earliestStart + node.duration;
        if (node.EF > criticalDuration) {
          criticalDuration = node.EF;
        }
      }
      // 反向:LS / LF
      for (let i = orderList.length - 1; i >= 0; i--) {
        const node = orderList[i];
        let latestFinish = criticalDuration;
        for (const lkItem of node.outgoing) {
          const toObjItem = nodeMap.get('' + lkItem.to);
          if (toObjItem) {
            const need = backwardCriticalPathUpperBound(lkItem.type, toObjItem.LS, toObjItem.LF, node.duration);
            if (need < latestFinish) {
              latestFinish = need;
            }
          }
        }
        node.LF = latestFinish;
        node.LS = latestFinish - node.duration;
      }
      // 关键任务
      const criticalSet = new Set();
      const criticalRowIds = [];
      for (const nodeItem of orderList) {
        if (Math.abs(nodeItem.LS - nodeItem.ES) < tolerance) {
          criticalSet.add(nodeItem.rowid);
          criticalRowIds.push(nodeItem.rowid);
          criticalRowList.push(nodeItem.row);
          criticalRowMaps.set(nodeItem.rowid, nodeItem.row);
        }
      }
      // 关键连接线
      const criticalLinks = [];
      for (const lkItem of linkList) {
        const toObjItem = nodeMap.get('' + lkItem.to);
        const fromObjItem = nodeMap.get('' + lkItem.from);
        if (!toObjItem || !fromObjItem) {
          continue;
        }
        // 两端必须都是关键任务
        if (!criticalSet.has(fromObjItem.rowid) || !criticalSet.has(toObjItem.rowid)) {
          continue;
        }
        // 约束必须是连接的
        if (isCriticalPathLinkTight(lkItem.type, fromObjItem.ES, fromObjItem.EF, toObjItem.ES, toObjItem.EF, tolerance)) {
          criticalLinks.push(lkItem.raw);
          criticalLinkKeyMaps.set(getTaskLinkKey(lkItem.from, lkItem.to, lkItem.type), lkItem.raw);
        }
      }
      ganttReactData.criticalLinks = criticalLinks;
      ganttReactData.criticalRowIds = criticalRowIds;
      ganttReactData.criticalPathFlag++;
    }
    const calcScrollbar = () => {
      const {
        scrollXWidth,
        scrollYHeight
      } = reactData;
      const {
        elemStore
      } = internalData;
      const scrollbarOpts = computeScrollbarOpts.value;
      const bodyWrapperElem = (0, _util.getRefElem)(elemStore['main-body-wrapper']);
      const xHandleEl = refScrollXHandleElem.value;
      const yHandleEl = refScrollYHandleElem.value;
      let overflowY = false;
      let overflowX = false;
      if (bodyWrapperElem) {
        overflowY = scrollYHeight > bodyWrapperElem.clientHeight;
        if (yHandleEl) {
          const scrollbarWidth = scrollbarOpts.width || yHandleEl.offsetWidth - yHandleEl.clientWidth || 14;
          reactData.scrollbarWidth = scrollbarWidth;
          ganttReactData.scrollbarWidth = scrollbarWidth;
        }
        reactData.overflowY = overflowY;
        ganttReactData.overflowY = overflowY;
        overflowX = scrollXWidth > bodyWrapperElem.clientWidth;
        if (xHandleEl) {
          const scrollbarHeight = scrollbarOpts.height || xHandleEl.offsetHeight - xHandleEl.clientHeight || 14;
          reactData.scrollbarHeight = scrollbarHeight;
          ganttReactData.scrollbarHeight = scrollbarHeight;
        }
        reactData.overflowX = overflowX;
        ganttReactData.overflowX = overflowX;
      }
    };
    const handleSubTaskMinMaxSize = ($xeTable, list) => {
      const {
        chartMaps
      } = internalData;
      const {
        computeTreeOpts
      } = $xeTable.getComputeMaps();
      const treeOpts = computeTreeOpts.value;
      const childrenField = treeOpts.children || treeOpts.childrenField;
      const typeField = computeTypeField.value;
      let minChildLeftSize = 0;
      let maxChildLeftSize = 0;
      _xeUtils.default.eachTree(list, childRow => {
        const childRowid = $xeTable.getRowid(childRow);
        const renderTaskType = _xeUtils.default.get(childRow, typeField);
        if ((0, _util.hasSubviewTask)(renderTaskType)) {
          return;
        }
        const childChartRest = childRowid ? chartMaps[childRowid] : null;
        if (childChartRest) {
          maxChildLeftSize = Math.max(maxChildLeftSize, childChartRest.oLeftSize + childChartRest.oWidthSize);
          minChildLeftSize = minChildLeftSize ? Math.min(minChildLeftSize, childChartRest.oLeftSize) : childChartRest.oLeftSize;
        }
      }, {
        children: childrenField
      });
      return {
        minSize: minChildLeftSize,
        maxSize: maxChildLeftSize
      };
    };
    const updateTaskChartStyle = () => {
      const {
        dragBarRow
      } = ganttInternalData;
      const {
        viewCellWidth
      } = reactData;
      const {
        elemStore,
        chartMaps
      } = internalData;
      const $xeTable = internalData.xeTable;
      const chartWrapper = (0, _util.getRefElem)(elemStore['main-chart-task-wrapper']);
      if (chartWrapper && $xeTable) {
        const {
          computeTreeOpts
        } = $xeTable.getComputeMaps();
        const treeOpts = computeTreeOpts.value;
        const childrenField = treeOpts.children || treeOpts.childrenField;
        _xeUtils.default.arrayEach(chartWrapper.children, rowEl => {
          const barEl = rowEl.children[0];
          if (!barEl) {
            return;
          }
          const rowid = rowEl.getAttribute('rowid');
          if (dragBarRow && $xeTable.getRowid(dragBarRow) === rowid) {
            return;
          }
          const chartRest = rowid ? chartMaps[rowid] : null;
          const row = chartRest ? chartRest.row : null;
          // 子任务视图
          if ((0, _dom.hasClass)(barEl, 'is--subview')) {
            const childWrapperEl = barEl.firstElementChild;
            if (childWrapperEl) {
              // 行内展示
              if ((0, _dom.hasClass)(childWrapperEl, 'is--inline')) {
                _xeUtils.default.arrayEach(childWrapperEl.children, childRowEl => {
                  const childBarEl = childRowEl.children[0];
                  const childRowid = childBarEl.getAttribute('rowid') || '';
                  const childChartRest = childRowid ? chartMaps[childRowid] : null;
                  if (childChartRest) {
                    const childRow = childChartRest.row;
                    // 如果是子视图
                    if ((0, _dom.hasClass)(childBarEl, 'is--subview')) {
                      const subChildren = childRow[childrenField];
                      const {
                        minSize: minChildLeftSize,
                        maxSize: maxChildLeftSize
                      } = handleSubTaskMinMaxSize($xeTable, subChildren);
                      childBarEl.style.left = `${viewCellWidth * minChildLeftSize}px`;
                      childBarEl.style.width = `${viewCellWidth * (maxChildLeftSize - minChildLeftSize)}px`;
                    } else {
                      childBarEl.style.left = `${(0, _util.getTaskBarLeft)(childChartRest, viewCellWidth)}px`;
                      if (!(0, _dom.hasClass)(childBarEl, 'is--milestone')) {
                        // 里程碑不需要宽度
                        childBarEl.style.width = `${(0, _util.getTaskBarWidth)(childChartRest, viewCellWidth)}px`;
                      }
                    }
                  }
                });
              } else {
                // 如果展开子任务
                const childRowEl = childWrapperEl.children[0];
                const childBarEl = childRowEl ? childRowEl.children[0] : null;
                if (childBarEl) {
                  const rowChildren = row ? row[childrenField] : [];
                  const {
                    minSize: minChildLeftSize,
                    maxSize: maxChildLeftSize
                  } = handleSubTaskMinMaxSize($xeTable, rowChildren);
                  childBarEl.style.left = `${viewCellWidth * minChildLeftSize}px`;
                  childBarEl.style.width = `${viewCellWidth * (maxChildLeftSize - minChildLeftSize)}px`;
                }
              }
            }
          } else {
            barEl.style.left = `${(0, _util.getTaskBarLeft)(chartRest, viewCellWidth)}px`;
            // 里程碑不需要宽度
            if (!(0, _dom.hasClass)(barEl, 'is--milestone')) {
              barEl.style.width = `${(0, _util.getTaskBarWidth)(chartRest, viewCellWidth)}px`;
            }
          }
        });
      }
      return (0, _vue.nextTick)();
    };
    const updateStyle = () => {
      const {
        showLeftView
      } = ganttReactData;
      const {
        scrollbarWidth,
        scrollbarHeight,
        headerGroups,
        tableColumn
      } = reactData;
      const {
        elemStore,
        visibleColumn
      } = internalData;
      const $xeTable = internalData.xeTable;
      const el = refElem.value;
      if (!el) {
        return;
      }
      if (!$xeGantt) {
        return;
      }
      const scrollbarOpts = computeScrollbarOpts.value;
      const scrollbarXToTop = computeScrollbarXToTop.value;
      const scrollbarYToLeft = computeScrollbarYToLeft.value;
      const xLeftCornerEl = refScrollXLeftCornerElem.value;
      const xRightCornerEl = refScrollXRightCornerElem.value;
      const scrollXVirtualEl = refScrollXVirtualElem.value;
      let osbWidth = scrollbarWidth;
      const osbHeight = scrollbarHeight;
      let tbHeight = 0;
      let tHeaderHeight = 0;
      let tFooterHeight = 0;
      if ($xeTable) {
        const tableInternalData = $xeTable.internalData;
        tbHeight = tableInternalData.tBodyHeight;
        tHeaderHeight = tableInternalData.tHeaderHeight;
        tFooterHeight = tableInternalData.tFooterHeight;
      }
      let yScrollbarVisible = 'visible';
      if (scrollbarYToLeft && showLeftView || scrollbarOpts.y && scrollbarOpts.y.visible === false) {
        osbWidth = 0;
        yScrollbarVisible = 'hidden';
      }
      const headerScrollElem = (0, _util.getRefElem)(elemStore['main-header-scroll']);
      if (headerScrollElem) {
        headerScrollElem.style.height = `${tHeaderHeight}px`;
        headerScrollElem.style.setProperty('--vxe-ui-gantt-view-cell-height', `${tHeaderHeight / headerGroups.length}px`);
      }
      const bodyScrollElem = (0, _util.getRefElem)(elemStore['main-body-scroll']);
      if (bodyScrollElem) {
        bodyScrollElem.style.height = `${tbHeight}px`;
      }
      const footerScrollElem = (0, _util.getRefElem)(elemStore['main-footer-scroll']);
      if (footerScrollElem) {
        footerScrollElem.style.height = `${tFooterHeight}px`;
      }
      if (scrollXVirtualEl) {
        scrollXVirtualEl.style.height = `${osbHeight}px`;
        scrollXVirtualEl.style.visibility = 'visible';
      }
      const xWrapperEl = refScrollXWrapperElem.value;
      if (xWrapperEl) {
        xWrapperEl.style.left = scrollbarXToTop ? `${osbWidth}px` : '';
        xWrapperEl.style.width = `${el.clientWidth - osbWidth}px`;
      }
      if (xLeftCornerEl) {
        xLeftCornerEl.style.width = scrollbarXToTop ? `${osbWidth}px` : '';
        xLeftCornerEl.style.display = scrollbarXToTop ? osbHeight ? 'block' : '' : '';
      }
      if (xRightCornerEl) {
        xRightCornerEl.style.width = scrollbarXToTop ? '' : `${osbWidth}px`;
        xRightCornerEl.style.display = scrollbarXToTop ? '' : osbHeight ? 'block' : '';
      }
      const scrollYVirtualEl = refScrollYVirtualElem.value;
      if (scrollYVirtualEl) {
        scrollYVirtualEl.style.width = `${osbWidth}px`;
        scrollYVirtualEl.style.height = `${tbHeight + tHeaderHeight + tFooterHeight}px`;
        scrollYVirtualEl.style.visibility = yScrollbarVisible;
      }
      const yTopCornerEl = refScrollYTopCornerElem.value;
      if (yTopCornerEl) {
        yTopCornerEl.style.height = `${tHeaderHeight}px`;
        yTopCornerEl.style.display = tHeaderHeight ? 'block' : '';
      }
      const yWrapperEl = refScrollYWrapperElem.value;
      if (yWrapperEl) {
        yWrapperEl.style.height = `${tbHeight}px`;
        yWrapperEl.style.top = `${tHeaderHeight}px`;
      }
      const yBottomCornerEl = refScrollYBottomCornerElem.value;
      if (yBottomCornerEl) {
        yBottomCornerEl.style.height = `${tFooterHeight}px`;
        yBottomCornerEl.style.top = `${tHeaderHeight + tbHeight}px`;
        yBottomCornerEl.style.display = tFooterHeight ? 'block' : '';
      }
      const colInfoElem = refColInfoElem.value;
      let viewCellWidth = 40;
      if (colInfoElem) {
        viewCellWidth = colInfoElem.clientWidth || 40;
      }
      let viewTableWidth = viewCellWidth;
      if (visibleColumn.length) {
        viewTableWidth = Math.max(0, viewCellWidth * visibleColumn.length);
        if (bodyScrollElem) {
          const viewWidth = bodyScrollElem.clientWidth;
          const remainWidth = viewWidth - viewTableWidth;
          if (remainWidth > 0) {
            viewCellWidth += Math.max(0, remainWidth / visibleColumn.length);
            viewTableWidth = viewWidth;
          }
        }
      }
      reactData.viewCellWidth = viewCellWidth;
      const headerTableElem = (0, _util.getRefElem)(elemStore['main-header-table']);
      const bodyTableElem = (0, _util.getRefElem)(elemStore['main-body-table']);
      const vmTableWidth = viewCellWidth * tableColumn.length;
      if (headerTableElem) {
        headerTableElem.style.width = `${viewTableWidth}px`;
      }
      if (bodyTableElem) {
        bodyTableElem.style.width = `${vmTableWidth}px`;
      }
      reactData.scrollXWidth = viewTableWidth;
      return Promise.all([updateTaskChartStyle(), $xeGantt.handleUpTaskLinkStyle ? $xeGantt.handleUpTaskLinkStyle($xeGanttView) : null]);
    };
    const handleRecalculateStyle = () => {
      const el = refElem.value;
      internalData.rceRunTime = Date.now();
      if (!el || !el.clientWidth) {
        return (0, _vue.nextTick)();
      }
      if (!$xeGantt) {
        return (0, _vue.nextTick)();
      }
      calcScrollbar();
      updateStyle();
      return computeScrollLoad();
    };
    const handleLazyRecalculate = () => {
      return new Promise(resolve => {
        const {
          rceTimeout,
          rceRunTime
        } = internalData;
        const $xeTable = internalData.xeTable;
        let refreshDelay = 30;
        if ($xeTable) {
          const {
            computeResizeOpts
          } = $xeTable.getComputeMaps();
          const resizeOpts = computeResizeOpts.value;
          refreshDelay = resizeOpts.refreshDelay || refreshDelay;
        }
        if (rceTimeout) {
          clearTimeout(rceTimeout);
          if (rceRunTime && rceRunTime + (refreshDelay - 5) < Date.now()) {
            resolve(handleRecalculateStyle());
          } else {
            (0, _vue.nextTick)(() => {
              resolve();
            });
          }
        } else {
          resolve(handleRecalculateStyle());
        }
        internalData.rceTimeout = setTimeout(() => {
          internalData.rceTimeout = undefined;
          handleRecalculateStyle();
        }, refreshDelay);
      });
    };
    const computeScrollLoad = () => {
      return (0, _vue.nextTick)().then(() => {
        const {
          scrollXLoad
        } = reactData;
        const {
          scrollXStore
        } = internalData;
        // 计算 X 逻辑
        if (scrollXLoad) {
          const {
            toVisibleIndex: toXVisibleIndex,
            visibleSize: visibleXSize
          } = handleVirtualXVisible();
          const offsetXSize = 2;
          scrollXStore.preloadSize = 1;
          scrollXStore.offsetSize = offsetXSize;
          scrollXStore.visibleSize = visibleXSize;
          scrollXStore.endIndex = Math.max(scrollXStore.startIndex + scrollXStore.visibleSize + offsetXSize, scrollXStore.endIndex);
          scrollXStore.visibleStartIndex = Math.max(scrollXStore.startIndex, toXVisibleIndex);
          scrollXStore.visibleEndIndex = Math.min(scrollXStore.endIndex, toXVisibleIndex + visibleXSize);
          updateScrollXData().then(() => {
            loadScrollXData();
          });
        } else {
          updateScrollXSpace();
        }
      });
    };
    const handleVirtualXVisible = () => {
      const {
        viewCellWidth
      } = reactData;
      const {
        elemStore
      } = internalData;
      const bodyScrollElem = (0, _util.getRefElem)(elemStore['main-body-scroll']);
      if (bodyScrollElem) {
        const clientWidth = bodyScrollElem.clientWidth;
        const scrollLeft = bodyScrollElem.scrollLeft;
        const toVisibleIndex = Math.floor(scrollLeft / viewCellWidth) - 1;
        const visibleSize = Math.ceil(clientWidth / viewCellWidth) + 1;
        return {
          toVisibleIndex: Math.max(0, toVisibleIndex),
          visibleSize: Math.max(1, visibleSize)
        };
      }
      return {
        toVisibleIndex: 0,
        visibleSize: 6
      };
    };
    const loadScrollXData = () => {
      const {
        isScrollXBig
      } = reactData;
      const {
        scrollXStore
      } = internalData;
      const {
        preloadSize,
        startIndex,
        endIndex,
        offsetSize
      } = scrollXStore;
      const {
        toVisibleIndex,
        visibleSize
      } = handleVirtualXVisible();
      const offsetItem = {
        startIndex: Math.max(0, isScrollXBig ? toVisibleIndex - 1 : toVisibleIndex - 1 - offsetSize - preloadSize),
        endIndex: isScrollXBig ? toVisibleIndex + visibleSize : toVisibleIndex + visibleSize + offsetSize + preloadSize
      };
      scrollXStore.visibleStartIndex = toVisibleIndex - 1;
      scrollXStore.visibleEndIndex = toVisibleIndex + visibleSize + 1;
      const {
        startIndex: offsetStartIndex,
        endIndex: offsetEndIndex
      } = offsetItem;
      if (toVisibleIndex <= startIndex || toVisibleIndex >= endIndex - visibleSize - 1) {
        if (startIndex !== offsetStartIndex || endIndex !== offsetEndIndex) {
          scrollXStore.startIndex = offsetStartIndex;
          scrollXStore.endIndex = offsetEndIndex;
          updateScrollXData();
        }
      }
    };
    const updateScrollXData = () => {
      handleTableColumn();
      updateScrollXSpace();
      return (0, _vue.nextTick)();
    };
    const updateScrollXStatus = () => {
      const scrollXLoad = true;
      reactData.scrollXLoad = scrollXLoad;
      return scrollXLoad;
    };
    const handleTableColumn = () => {
      const {
        scrollXLoad
      } = reactData;
      const {
        visibleColumn,
        scrollXStore
      } = internalData;
      const tableColumn = scrollXLoad ? visibleColumn.slice(scrollXStore.startIndex, scrollXStore.endIndex) : visibleColumn.slice(0);
      reactData.tableColumn = tableColumn;
    };
    const updateScrollXSpace = () => {
      const {
        scrollXLoad,
        scrollXWidth,
        viewCellWidth
      } = reactData;
      const {
        elemStore,
        scrollXStore
      } = internalData;
      const bodyTableElem = (0, _util.getRefElem)(elemStore['main-body-table']);
      // const headerTableElem = getRefElem(elemStore['main-header-table'])
      // const footerTableElem = getRefElem(elemStore['main-footer-table'])
      const {
        startIndex
      } = scrollXStore;
      let xSpaceLeft = 0;
      if (scrollXLoad) {
        xSpaceLeft = Math.max(0, startIndex * viewCellWidth);
      }
      // if (headerTableElem) {
      //   headerTableElem.style.transform = `translate(${xSpaceLeft}px, 0px)`
      // }
      if (bodyTableElem) {
        bodyTableElem.style.transform = `translate(${xSpaceLeft}px, ${reactData.scrollYTop || 0}px)`;
      }
      // if (footerTableElem) {
      //   footerTableElem.style.transform = `translate(${xSpaceLeft}px, 0px)`
      // }
      const ySpaceWidth = scrollXWidth;
      const layoutList = ['header', 'body', 'footer'];
      layoutList.forEach(layout => {
        const xSpaceElem = (0, _util.getRefElem)(elemStore[`main-${layout}-xSpace`]);
        if (xSpaceElem) {
          xSpaceElem.style.width = scrollXLoad ? `${ySpaceWidth}px` : '';
        }
      });
      const scrollXSpaceEl = refScrollXSpaceElem.value;
      if (scrollXSpaceEl) {
        scrollXSpaceEl.style.width = `${ySpaceWidth}px`;
      }
      const beforeWrapper = (0, _util.getRefElem)(elemStore['main-chart-before-wrapper']);
      const beforeSvgElem = beforeWrapper ? beforeWrapper.firstElementChild : null;
      if (beforeSvgElem) {
        beforeSvgElem.style.width = `${ySpaceWidth}px`;
      }
      const afterWrapper = (0, _util.getRefElem)(elemStore['main-chart-after-wrapper']);
      const afterSvgElem = afterWrapper ? afterWrapper.firstElementChild : null;
      if (afterSvgElem) {
        afterSvgElem.style.width = `${ySpaceWidth}px`;
      }
      reactData.scrollXLeft = xSpaceLeft;
      reactData.scrollXWidth = ySpaceWidth;
      calcScrollbar();
      return (0, _vue.nextTick)();
    };
    const triggerScrollXEvent = () => {
      loadScrollXData();
    };
    const updateScrollYSpace = () => {
      const {
        scrollYLoad,
        overflowY
      } = reactData;
      const {
        elemStore
      } = internalData;
      const $xeTable = internalData.xeTable;
      const bodyScrollElem = (0, _util.getRefElem)(elemStore['main-body-scroll']);
      const bodyTableElem = (0, _util.getRefElem)(elemStore['main-body-table']);
      let ySpaceTop = 0;
      let scrollYHeight = 0;
      let isScrollYBig = false;
      if ($xeTable) {
        const tableReactData = $xeTable.reactData;
        ySpaceTop = tableReactData.scrollYTop;
        scrollYHeight = tableReactData.scrollYHeight;
        isScrollYBig = tableReactData.isScrollYBig;
      }
      let ySpaceHeight = scrollYHeight;
      let scrollYTop = ySpaceTop;
      let clientHeight = 0;
      if (bodyScrollElem) {
        clientHeight = bodyScrollElem.clientHeight;
      }
      if (isScrollYBig) {
        // 触底
        if (bodyScrollElem && bodyTableElem && bodyScrollElem.scrollTop + clientHeight >= maxYHeight) {
          scrollYTop = maxYHeight - bodyTableElem.clientHeight;
        } else {
          scrollYTop = (maxYHeight - clientHeight) * (ySpaceTop / (scrollYHeight - clientHeight));
        }
        ySpaceHeight = maxYHeight;
      }
      if (!(scrollYLoad && overflowY)) {
        scrollYTop = 0;
      }
      const bodyChartWrapperElem = (0, _util.getRefElem)(elemStore['main-chart-task-wrapper']);
      if (bodyTableElem) {
        bodyTableElem.style.transform = `translate(${reactData.scrollXLeft || 0}px, ${scrollYTop}px)`;
      }
      if (bodyChartWrapperElem) {
        bodyChartWrapperElem.style.transform = `translateY(${scrollYTop}px)`;
      }
      const bodyYSpaceElem = (0, _util.getRefElem)(elemStore['main-body-ySpace']);
      if (bodyYSpaceElem) {
        bodyYSpaceElem.style.height = ySpaceHeight ? `${ySpaceHeight}px` : '';
      }
      const scrollYSpaceEl = refScrollYSpaceElem.value;
      if (scrollYSpaceEl) {
        scrollYSpaceEl.style.height = ySpaceHeight ? `${ySpaceHeight}px` : '';
      }
      const beforeWrapper = (0, _util.getRefElem)(elemStore['main-chart-before-wrapper']);
      const beforeSvgElem = beforeWrapper ? beforeWrapper.firstElementChild : null;
      if (beforeSvgElem) {
        beforeSvgElem.style.height = ySpaceHeight ? `${ySpaceHeight}px` : '';
      }
      const afterWrapper = (0, _util.getRefElem)(elemStore['main-chart-after-wrapper']);
      const afterSvgElem = afterWrapper ? afterWrapper.firstElementChild : null;
      if (afterSvgElem) {
        afterSvgElem.style.height = ySpaceHeight ? `${ySpaceHeight}px` : '';
      }
      const nowLineElem = (0, _util.getRefElem)(elemStore['main-chart-now-line']);
      if (nowLineElem) {
        nowLineElem.style.height = ySpaceHeight ? `${ySpaceHeight}px` : '';
      }
      reactData.scrollYTop = scrollYTop;
      reactData.scrollYHeight = scrollYHeight;
      reactData.isScrollYBig = isScrollYBig;
      calcScrollbar();
      return (0, _vue.nextTick)().then(() => {
        updateStyle();
      });
    };
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const checkLastSyncScroll = (isRollX, isRollY) => {
      const {
        lcsTimeout
      } = internalData;
      reactData.lazScrollLoading = true;
      if (lcsTimeout) {
        clearTimeout(lcsTimeout);
      }
      internalData.lcsTimeout = setTimeout(() => {
        internalData.lcsRunTime = Date.now();
        internalData.lcsTimeout = undefined;
        internalData.intoRunScroll = false;
        internalData.inVirtualScroll = false;
        internalData.inWheelScroll = false;
        internalData.inHeaderScroll = false;
        internalData.inBodyScroll = false;
        internalData.inFooterScroll = false;
        reactData.lazScrollLoading = false;
      }, 200);
    };
    const handleScrollData = (isRollY, isRollX, scrollTop, scrollLeft) => {
      if (isRollX) {
        internalData.lastScrollLeft = scrollLeft;
      }
      if (isRollY) {
        internalData.lastScrollTop = scrollTop;
      }
      reactData.lastScrollTime = Date.now();
      checkLastSyncScroll(isRollX, isRollY);
    };
    const handleScrollEvent = (evnt, isRollY, isRollX, scrollTop, scrollLeft) => {
      const $xeTable = internalData.xeTable;
      const {
        lastScrollLeft,
        lastScrollTop
      } = internalData;
      const xHandleEl = refScrollXHandleElem.value;
      const yHandleEl = refScrollYHandleElem.value;
      if (!xHandleEl || !yHandleEl) {
        return;
      }
      if (!$xeTable) {
        return;
      }
      const {
        computeScrollXThreshold,
        computeScrollYThreshold
      } = $xeTable.getComputeMaps();
      const bodyHeight = yHandleEl.clientHeight;
      const bodyWidth = xHandleEl.clientWidth;
      const scrollHeight = yHandleEl.scrollHeight;
      const scrollWidth = xHandleEl.scrollWidth;
      let isTop = false;
      let isBottom = false;
      let isLeft = false;
      let isRight = false;
      let direction = '';
      let isTopBoundary = false;
      let isBottomBoundary = false;
      let isLeftBoundary = false;
      let isRightBoundary = false;
      if (isRollX) {
        const xThreshold = computeScrollXThreshold.value;
        isLeft = scrollLeft <= 0;
        if (!isLeft) {
          isRight = scrollLeft + bodyWidth >= scrollWidth - 1;
        }
        if (scrollLeft > lastScrollLeft) {
          direction = 'right';
          if (scrollLeft + bodyWidth >= scrollWidth - xThreshold) {
            isRightBoundary = true;
          }
        } else {
          direction = 'left';
          if (scrollLeft <= xThreshold) {
            isLeftBoundary = true;
          }
        }
      }
      if (isRollY) {
        const yThreshold = computeScrollYThreshold.value;
        isTop = scrollTop <= 0;
        if (!isTop) {
          isBottom = scrollTop + bodyHeight >= scrollHeight - 1;
        }
        if (scrollTop > lastScrollTop) {
          direction = 'bottom';
          if (scrollTop + bodyHeight >= scrollHeight - yThreshold) {
            isBottomBoundary = true;
          }
        } else {
          direction = 'top';
          if (scrollTop <= yThreshold) {
            isTopBoundary = true;
          }
        }
      }
      handleScrollData(isRollY, isRollX, scrollTop, scrollLeft);
      const evntParams = {
        source: sourceType,
        scrollTop,
        scrollLeft,
        bodyHeight,
        bodyWidth,
        scrollHeight,
        scrollWidth,
        isX: isRollX,
        isY: isRollY,
        isTop,
        isBottom,
        isLeft,
        isRight,
        direction
      };
      if (isBottomBoundary || isTopBoundary || isRightBoundary || isLeftBoundary) {
        $xeGantt.dispatchEvent('scroll-boundary', evntParams, evnt);
      }
      $xeGantt.dispatchEvent('scroll', evntParams, evnt);
    };
    const ganttViewMethods = {
      refreshData() {
        handleUpdateData();
        handleRecalculateStyle();
        return (0, _vue.nextTick)().then(() => {
          const $xeTable = internalData.xeTable;
          handleRecalculateStyle();
          if ($xeTable) {
            return $xeTable.recalculate();
          }
        });
      },
      updateViewData(force) {
        const $xeTable = internalData.xeTable;
        if ($xeTable) {
          const tableReactData = $xeTable.reactData;
          const {
            tableData
          } = tableReactData;
          reactData.tableData = tableData;
          if (force) {
            ganttReactData.currLeftSpacing = 0;
            ganttReactData.currRightSpacing = 0;
            handleUpdateData();
          }
          handleRecalculateStyle();
        }
        return (0, _vue.nextTick)();
      },
      connectUpdate({
        $table
      }) {
        if ($table) {
          internalData.xeTable = $table;
        }
        return (0, _vue.nextTick)();
      }
    };
    /**
     * 同步表格滚动
     */
    const syncTableScrollTop = scrollTop => {
      const $xeTable = internalData.xeTable;
      if ($xeTable) {
        const tableInternalData = $xeTable.internalData;
        const {
          elemStore: tableElemStore
        } = tableInternalData;
        const tableBodyScrollElem = (0, _util.getRefElem)(tableElemStore['main-body-scroll']);
        if (tableBodyScrollElem) {
          tableBodyScrollElem.scrollTop = scrollTop;
        }
      }
    };
    const ganttViewPrivateMethods = {
      handleUpdateStyle: updateStyle,
      handleLazyRecalculate,
      handleUpdateCurrentRow(row) {
        const $xeTable = internalData.xeTable;
        const el = refElem.value;
        if ($xeTable && el) {
          if (row) {
            const tableProps = $xeTable.props;
            const {
              computeRowOpts
            } = $xeTable.getComputeMaps();
            const rowOpts = computeRowOpts.value;
            if (rowOpts.isCurrent || tableProps.highlightCurrentRow) {
              _xeUtils.default.arrayEach(el.querySelectorAll(`.vxe-gantt-view--body-row[rowid="${$xeTable.getRowid(row)}"]`), elem => (0, _dom.addClass)(elem, 'row--current'));
            }
          } else {
            _xeUtils.default.arrayEach(el.querySelectorAll('.vxe-gantt-view--body-row.row--current'), elem => (0, _dom.removeClass)(elem, 'row--current'));
          }
        }
      },
      handleUpdateHoverRow(row) {
        const $xeTable = internalData.xeTable;
        const el = refElem.value;
        if ($xeTable && el) {
          if (row) {
            _xeUtils.default.arrayEach(el.querySelectorAll(`.vxe-gantt-view--body-row[rowid="${$xeTable.getRowid(row)}"]`), elem => (0, _dom.addClass)(elem, 'row--hover'));
          } else {
            _xeUtils.default.arrayEach(el.querySelectorAll('.vxe-gantt-view--body-row.row--hover'), elem => (0, _dom.removeClass)(elem, 'row--hover'));
          }
        }
      },
      triggerHeaderScrollEvent(evnt) {
        const {
          elemStore,
          inVirtualScroll,
          inBodyScroll,
          inFooterScroll
        } = internalData;
        if (inVirtualScroll) {
          return;
        }
        if (inBodyScroll || inFooterScroll) {
          return;
        }
        const wrapperEl = evnt.currentTarget;
        const bodyScrollElem = (0, _util.getRefElem)(elemStore['main-body-scroll']);
        const xHandleEl = refScrollXHandleElem.value;
        if (bodyScrollElem && wrapperEl) {
          const isRollX = true;
          const isRollY = false;
          const currLeftNum = wrapperEl.scrollLeft;
          internalData.inHeaderScroll = true;
          (0, _dom.setScrollLeft)(xHandleEl, currLeftNum);
          (0, _dom.setScrollLeft)(bodyScrollElem, currLeftNum);
          handleScrollEvent(evnt, isRollY, isRollX, wrapperEl.scrollTop, currLeftNum);
        }
      },
      triggerBodyScrollEvent(evnt) {
        const {
          scrollXLoad
        } = reactData;
        const {
          elemStore,
          inVirtualScroll,
          inHeaderScroll,
          inFooterScroll,
          lastScrollLeft,
          lastScrollTop
        } = internalData;
        if (inVirtualScroll) {
          return;
        }
        if (inHeaderScroll || inFooterScroll) {
          return;
        }
        const wrapperEl = evnt.currentTarget;
        const headerScrollElem = (0, _util.getRefElem)(elemStore['main-header-scroll']);
        const xHandleEl = refScrollXHandleElem.value;
        const yHandleEl = refScrollYHandleElem.value;
        const scrollLeft = wrapperEl.scrollLeft;
        const scrollTop = wrapperEl.scrollTop;
        const isRollX = scrollLeft !== lastScrollLeft;
        const isRollY = scrollTop !== lastScrollTop;
        internalData.inBodyScroll = true;
        internalData.scrollRenderType = '';
        if (isRollY) {
          (0, _dom.setScrollTop)(yHandleEl, scrollTop);
          syncTableScrollTop(scrollTop);
        }
        if (isRollX) {
          internalData.inBodyScroll = true;
          (0, _dom.setScrollLeft)(xHandleEl, scrollLeft);
          (0, _dom.setScrollLeft)(headerScrollElem, scrollLeft);
          if (scrollXLoad) {
            triggerScrollXEvent();
          }
        }
        if (isRollY) {
          handleScrollData(isRollY, isRollX, wrapperEl.scrollTop, scrollLeft);
        }
        if (isRollX) {
          handleScrollEvent(evnt, isRollY, isRollX, wrapperEl.scrollTop, scrollLeft);
        }
      },
      // triggerFooterScrollEvent (evnt) {
      //   const { inVirtualScroll, inHeaderScroll, inBodyScroll } = internalData
      //   if (inVirtualScroll) {
      //     return
      //   }
      //   if (inHeaderScroll || inBodyScroll) {
      //     return
      //   }
      //   const wrapperEl = evnt.currentTarget as HTMLDivElement
      //   if (wrapperEl) {
      //     const isRollX = true
      //     const isRollY = false
      //     const currLeftNum = wrapperEl.scrollLeft
      //     handleScrollEvent(evnt, isRollY, isRollX, wrapperEl.scrollTop, currLeftNum)
      //   }
      // },
      triggerVirtualScrollXEvent(evnt) {
        const {
          scrollXLoad
        } = reactData;
        const {
          elemStore,
          inHeaderScroll,
          inBodyScroll
        } = internalData;
        if (inHeaderScroll || inBodyScroll) {
          return;
        }
        const wrapperEl = evnt.currentTarget;
        const headerScrollElem = (0, _util.getRefElem)(elemStore['main-header-scroll']);
        const bodyScrollElem = (0, _util.getRefElem)(elemStore['main-body-scroll']);
        if (wrapperEl) {
          const isRollY = false;
          const isRollX = true;
          const currLeftNum = wrapperEl.scrollLeft;
          internalData.inVirtualScroll = true;
          (0, _dom.setScrollLeft)(headerScrollElem, currLeftNum);
          (0, _dom.setScrollLeft)(bodyScrollElem, currLeftNum);
          if (scrollXLoad) {
            triggerScrollXEvent();
          }
          handleScrollEvent(evnt, isRollY, isRollX, wrapperEl.scrollTop, currLeftNum);
        }
      },
      triggerVirtualScrollYEvent(evnt) {
        const {
          elemStore,
          inHeaderScroll,
          inBodyScroll
        } = internalData;
        if (inHeaderScroll || inBodyScroll) {
          return;
        }
        const wrapperEl = evnt.currentTarget;
        const bodyScrollElem = (0, _util.getRefElem)(elemStore['main-body-scroll']);
        if (wrapperEl) {
          const isRollY = true;
          const isRollX = false;
          const currTopNum = wrapperEl.scrollTop;
          internalData.inVirtualScroll = true;
          (0, _dom.setScrollTop)(bodyScrollElem, currTopNum);
          syncTableScrollTop(currTopNum);
          handleScrollData(isRollY, isRollX, currTopNum, wrapperEl.scrollLeft);
        }
      },
      handleUpdateSXSpace() {
        return updateScrollXSpace();
      },
      handleUpdateSYSpace() {
        return updateScrollYSpace();
      },
      handleUpdateSYStatus(sYLoad) {
        reactData.scrollYLoad = sYLoad;
      }
    };
    const handleGlobalResizeEvent = () => {
      handleLazyRecalculate();
    };
    Object.assign($xeGanttView, ganttViewMethods, ganttViewPrivateMethods);
    const renderScrollX = () => {
      return (0, _vue.h)('div', {
        key: 'vsx',
        ref: refScrollXVirtualElem,
        class: 'vxe-gantt-view--scroll-x-virtual'
      }, [(0, _vue.h)('div', {
        ref: refScrollXLeftCornerElem,
        class: 'vxe-gantt-view--scroll-x-left-corner'
      }), (0, _vue.h)('div', {
        ref: refScrollXWrapperElem,
        class: 'vxe-gantt-view--scroll-x-wrapper'
      }, [(0, _vue.h)('div', {
        ref: refScrollXHandleElem,
        class: 'vxe-gantt-view--scroll-x-handle',
        onScroll: $xeGanttView.triggerVirtualScrollXEvent
      }, [(0, _vue.h)('div', {
        ref: refScrollXSpaceElem,
        class: 'vxe-gantt-view--scroll-x-space'
      })]), (0, _vue.h)('div', {
        class: 'vxe-gantt-view--scroll-x-handle-appearance'
      })]), (0, _vue.h)('div', {
        ref: refScrollXRightCornerElem,
        class: 'vxe-gantt-view--scroll-x-right-corner'
      })]);
    };
    const renderScrollY = () => {
      return (0, _vue.h)('div', {
        ref: refScrollYVirtualElem,
        class: 'vxe-gantt-view--scroll-y-virtual'
      }, [(0, _vue.h)('div', {
        ref: refScrollYTopCornerElem,
        class: 'vxe-gantt-view--scroll-y-top-corner'
      }), (0, _vue.h)('div', {
        ref: refScrollYWrapperElem,
        class: 'vxe-gantt-view--scroll-y-wrapper'
      }, [(0, _vue.h)('div', {
        ref: refScrollYHandleElem,
        class: 'vxe-gantt-view--scroll-y-handle',
        onScroll: $xeGanttView.triggerVirtualScrollYEvent
      }, [(0, _vue.h)('div', {
        ref: refScrollYSpaceElem,
        class: 'vxe-gantt-view--scroll-y-space'
      })]), (0, _vue.h)('div', {
        class: 'vxe-gantt-view--scroll-y-handle-appearance'
      })]), (0, _vue.h)('div', {
        ref: refScrollYBottomCornerElem,
        class: 'vxe-gantt-view--scroll-y-bottom-corner'
      })]);
    };
    const renderViewport = () => {
      return (0, _vue.h)('div', {
        class: 'vxe-gantt-view--viewport-wrapper'
      }, [(0, _vue.h)(_ganttHeader.default), (0, _vue.h)(_ganttBody.default), (0, _vue.h)(_ganttFooter.default)]);
    };
    const renderBody = () => {
      const scrollbarYToLeft = computeScrollbarYToLeft.value;
      return (0, _vue.h)('div', {
        class: 'vxe-gantt-view--layout-wrapper'
      }, scrollbarYToLeft ? [renderScrollY(), renderViewport()] : [renderViewport(), renderScrollY()]);
    };
    const renderVN = () => {
      const {
        overflowX,
        overflowY,
        scrollXLoad,
        scrollYLoad
      } = reactData;
      const scrollbarXToTop = computeScrollbarXToTop.value;
      return (0, _vue.h)('div', {
        ref: refElem,
        class: ['vxe-gantt-view', {
          'is--scroll-y': overflowY,
          'is--scroll-x': overflowX,
          'is--virtual-x': scrollXLoad,
          'is--virtual-y': scrollYLoad
        }]
      }, [(0, _vue.h)('div', {
        class: 'vxe-gantt-view--render-wrapper'
      }, scrollbarXToTop ? [renderScrollX(), renderBody()] : [renderBody(), renderScrollX()]), (0, _vue.h)('div', {
        class: 'vxe-gantt-view--render-vars'
      }, [(0, _vue.h)('div', {
        ref: refColInfoElem,
        class: 'vxe-gantt-view--column-info'
      })])]);
    };
    (0, _vue.onMounted)(() => {
      globalEvents.on($xeGanttView, 'resize', handleGlobalResizeEvent);
    });
    (0, _vue.onBeforeUnmount)(() => {
      _xeUtils.default.assign(reactData, createReactData());
      _xeUtils.default.assign(internalData, createInternalData());
    });
    (0, _vue.onUnmounted)(() => {
      globalEvents.off($xeGanttView, 'keydown');
    });
    $xeGanttView.renderVN = renderVN;
    (0, _vue.provide)('$xeGanttView', $xeGanttView);
    return $xeGanttView;
  },
  render() {
    return this.renderVN();
  }
});