vxe-gantt
Version:
A vue based gantt component
261 lines (260 loc) • 12.3 kB
JavaScript
import { h, inject, ref, onMounted, onUnmounted } from 'vue';
import { defineVxeComponent } from '../../ui/src/comp';
import { getCellRestHeight } from './util';
import { getClass } from '../../ui/src/utils';
import XEUtils from 'xe-utils';
import GanttViewChartComponent from './gantt-chart';
const sourceType = 'gantt';
const viewType = 'body';
export default defineVxeComponent({
name: 'VxeGanttViewBody',
setup() {
const $xeGantt = inject('$xeGantt', {});
const $xeGanttView = inject('$xeGanttView', {});
const { computeTaskViewOpts, computeScaleUnit } = $xeGantt.getComputeMaps();
const { reactData, internalData } = $xeGanttView;
const refElem = ref();
const refBodyScroll = ref();
const refBodyTable = ref();
const refBodyXSpace = ref();
const refBodyYSpace = ref();
const renderColumn = ($xeTable, row, rowid, rowIndex, $rowIndex, _rowIndex, column, $columnIndex) => {
const tableReactData = $xeTable.reactData;
const { resizeHeightFlag } = tableReactData;
const tableInternalData = $xeTable.internalData;
const { fullAllDataRowIdData, visibleColumn } = tableInternalData;
const { computeCellOpts, computeRowOpts, computeDefaultRowHeight, computeResizableOpts } = $xeTable.getComputeMaps();
const cellOpts = computeCellOpts.value;
const rowOpts = computeRowOpts.value;
const defaultRowHeight = computeDefaultRowHeight.value;
const resizableOpts = computeResizableOpts.value;
const { isAllRowDrag } = resizableOpts;
const { headerGroups } = reactData;
const { todayDateMaps } = internalData;
const taskViewOpts = computeTaskViewOpts.value;
const { showNowLine, viewStyle } = taskViewOpts;
const scaleUnit = computeScaleUnit.value;
const { scaleItem } = headerGroups[headerGroups.length - 1] || {};
const { field, dateObj } = column;
const { cellClassName, cellStyle } = viewStyle || {};
const todayValue = showNowLine && scaleItem ? todayDateMaps[scaleItem.type] : null;
const rowRest = fullAllDataRowIdData[rowid] || {};
const cellHeight = resizeHeightFlag ? getCellRestHeight(rowRest, cellOpts, rowOpts, defaultRowHeight) : 0;
const tdVNs = [];
if (isAllRowDrag && rowOpts.resizable) {
const cellParams = {
$table: $xeTable,
$grid: null,
$gantt: $xeGantt,
seq: -1,
rowid,
row,
rowIndex,
$rowIndex,
_rowIndex,
column: visibleColumn[0],
columnIndex: 0,
$columnIndex: 0,
_columnIndex: 0,
fixed: '',
source: sourceType,
type: viewType,
isHidden: false,
isEdit: false,
level: -1,
// 已废弃属性
visibleData: [],
data: [],
items: []
};
tdVNs.push(h('div', {
class: 'vxe-gantt-view-cell--row-resizable',
onMousedown: (evnt) => $xeTable.handleRowResizeMousedownEvent(evnt, cellParams),
onDblclick: (evnt) => $xeTable.handleRowResizeDblclickEvent(evnt, cellParams)
}));
}
const ctParams = {
$gantt: $xeGantt,
source: sourceType,
type: viewType,
scaleType: scaleUnit,
dateObj,
row,
column,
$rowIndex,
rowIndex,
_rowIndex
};
return h('td', {
key: cellClassName || cellStyle ? field : $columnIndex,
class: [
'vxe-gantt-view--body-column',
{
'is--now': showNowLine && todayValue === field
},
getClass(cellClassName, ctParams)
],
style: cellStyle
? Object.assign({}, XEUtils.isFunction(cellStyle) ? cellStyle(ctParams) : cellStyle, {
height: `${cellHeight}px`
})
: {
height: `${cellHeight}px`
},
onClick(evnt) {
$xeGantt.handleTaskCellClickEvent(evnt, { row, column });
},
onDblclick(evnt) {
$xeGantt.handleTaskCellDblclickEvent(evnt, { row, column });
},
onContextmenu(evnt) {
$xeGantt.handleTaskBodyContextmenuEvent(evnt, ctParams);
}
}, tdVNs);
};
const renderRows = ($xeTable, tableData) => {
const tableProps = $xeTable.props;
const { treeConfig, stripe, highlightHoverRow, editConfig } = tableProps;
const tableReactData = $xeTable.reactData;
const { treeExpandedFlag, selectRadioRow, pendingRowFlag, isRowGroupStatus } = tableReactData;
const tableInternalData = $xeTable.internalData;
const { fullAllDataRowIdData, treeExpandedMaps, pendingRowMaps } = tableInternalData;
const { computeRadioOpts, computeCheckboxOpts, computeTreeOpts, computeRowOpts } = $xeTable.getComputeMaps();
const radioOpts = computeRadioOpts.value;
const checkboxOpts = computeCheckboxOpts.value;
const rowOpts = computeRowOpts.value;
const treeOpts = computeTreeOpts.value;
const { transform } = treeOpts;
const childrenField = treeOpts.children || treeOpts.childrenField;
const scaleUnit = computeScaleUnit.value;
const taskViewOpts = computeTaskViewOpts.value;
const { viewStyle } = taskViewOpts;
const { rowClassName, rowStyle, cellClassName, cellStyle } = viewStyle || {};
const { tableColumn, scrollYLoad } = reactData;
const trVNs = [];
tableData.forEach((row, $rowIndex) => {
const rowid = $xeTable.getRowid(row);
const rowRest = fullAllDataRowIdData[rowid] || {};
const trOns = {};
let rowIndex = $rowIndex;
let _rowIndex = -1;
if (rowRest) {
rowIndex = rowRest.index;
_rowIndex = rowRest._index;
}
// 是否新增行
let isNewRow = false;
if (editConfig) {
isNewRow = $xeTable.isInsertByRow(row);
}
// 当前行事件
if (rowOpts.isHover || highlightHoverRow) {
trOns.onMouseenter = (evnt) => {
$xeTable.triggerHoverEvent(evnt, { row, rowIndex });
};
trOns.onMouseleave = () => {
$xeTable.clearHoverRow();
};
}
// 拖拽行事件
if (rowOpts.drag && !isRowGroupStatus && (!treeConfig || transform)) {
trOns.onDragstart = $xeTable.handleRowDragDragstartEvent;
trOns.onDragend = $xeTable.handleRowDragDragendEvent;
trOns.onDragover = $xeTable.handleRowDragDragoverEvent;
}
const rowParams = {
$gantt: $xeGantt,
source: sourceType,
type: viewType,
scaleType: scaleUnit,
row,
rowIndex,
$rowIndex,
_rowIndex
};
trVNs.push(h('tr', Object.assign({ key: rowClassName || rowStyle || cellClassName || cellStyle ? rowid : $rowIndex, class: [
'vxe-gantt-view--body-row',
{
'row--stripe': stripe && (_rowIndex + 1) % 2 === 0,
'is--new': isNewRow,
'row--radio': radioOpts.highlight && $xeTable.eqRow(selectRadioRow, row),
'row--checked': checkboxOpts.highlight && $xeTable.isCheckedByCheckboxRow(row),
'row--pending': !!pendingRowFlag && !!pendingRowMaps[rowid]
},
getClass(rowClassName, rowParams)
], rowid, style: rowStyle ? (XEUtils.isFunction(rowStyle) ? rowStyle(rowParams) || undefined : rowStyle) : undefined }, trOns), tableColumn.map((column, $columnIndex) => renderColumn($xeTable, row, rowid, rowIndex, $rowIndex, _rowIndex, column, $columnIndex))));
let isExpandTree = false;
let rowChildren = [];
if (treeConfig && !scrollYLoad && !transform) {
rowChildren = row[childrenField];
isExpandTree = !!treeExpandedFlag && rowChildren && rowChildren.length > 0 && !!treeExpandedMaps[rowid];
}
// 如果是树形表格
if (isExpandTree) {
trVNs.push(...renderRows($xeTable, rowChildren));
}
});
return trVNs;
};
const renderVN = () => {
const $xeTable = $xeGanttView.internalData.xeTable;
const { tableData, tableColumn, viewCellWidth } = reactData;
return h('div', {
ref: refElem,
class: 'vxe-gantt-view--body-wrapper'
}, [
h('div', {
ref: refBodyScroll,
class: 'vxe-gantt-view--body-inner-wrapper',
onScroll: $xeGanttView.triggerBodyScrollEvent,
onContextmenu(evnt) {
$xeGantt.handleTaskBodyContextmenuEvent(evnt, { source: sourceType, type: viewType, rowIndex: -1, $rowIndex: -1, _rowIndex: -1 });
}
}, [
h('div', {
ref: refBodyXSpace,
class: 'vxe-body--x-space'
}),
h('div', {
ref: refBodyYSpace,
class: 'vxe-body--y-space'
}),
h('table', {
ref: refBodyTable,
class: 'vxe-gantt-view--body-table'
}, [
h('colgroup', {}, tableColumn.map((column, cIndex) => {
return h('col', {
key: cIndex,
style: {
width: `${viewCellWidth}px`
}
});
})),
h('tbody', {}, $xeTable ? renderRows($xeTable, tableData) : [])
]),
h(GanttViewChartComponent)
])
]);
};
onMounted(() => {
const { elemStore } = internalData;
const prefix = 'main-body-';
elemStore[`${prefix}wrapper`] = refElem;
elemStore[`${prefix}scroll`] = refBodyScroll;
elemStore[`${prefix}table`] = refBodyTable;
elemStore[`${prefix}xSpace`] = refBodyXSpace;
elemStore[`${prefix}ySpace`] = refBodyYSpace;
});
onUnmounted(() => {
const { elemStore } = internalData;
const prefix = 'main-body-';
elemStore[`${prefix}wrapper`] = null;
elemStore[`${prefix}scroll`] = null;
elemStore[`${prefix}table`] = null;
elemStore[`${prefix}xSpace`] = null;
elemStore[`${prefix}ySpace`] = null;
});
return renderVN;
}
});