vxe-gantt
Version:
A vue based gantt component
2,443 lines • 94.1 kB
JavaScript
"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();
}
});